Merge branch 'merge'
authorPaul Mackerras <paulus@samba.org>
Tue, 1 Aug 2006 00:37:25 +0000 (10:37 +1000)
committerPaul Mackerras <paulus@samba.org>
Tue, 1 Aug 2006 00:37:25 +0000 (10:37 +1000)
31 files changed:
1  2 
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/powermac/backlight.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/pseries/ras.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/xics.c
drivers/char/hvsi.c
drivers/i2c/busses/i2c-powermac.c
drivers/macintosh/macio_asic.c
drivers/macintosh/smu.c
drivers/macintosh/via-pmu.c
drivers/net/spider_net.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/mac53c94.c
drivers/scsi/mesh.c
drivers/video/S3triofb.c
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_pm.c
drivers/video/offb.c
drivers/video/riva/fbdev.c
include/asm-powerpc/system.h

@@@ -167,7 -167,7 +167,7 @@@ static DEVICE_ATTR(name, S_IRUSR | S_IR
                   NULL);
  
  static struct ibmebus_dev* __devinit ibmebus_register_device_common(
 -      struct ibmebus_dev *dev, char *name)
 +      struct ibmebus_dev *dev, const char *name)
  {
        int err = 0;
  
@@@ -194,10 -194,10 +194,10 @@@ static struct ibmebus_dev* __devinit ib
        struct device_node *dn)
  {
        struct ibmebus_dev *dev;
 -      char *loc_code;
 +      const char *loc_code;
        int length;
  
 -      loc_code = (char *)get_property(dn, "ibm,loc-code", NULL);
 +      loc_code = get_property(dn, "ibm,loc-code", NULL);
        if (!loc_code) {
                  printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
                       __FUNCTION__, dn->name ? dn->name : "<unknown>");
@@@ -323,7 -323,7 +323,7 @@@ int ibmebus_request_irq(struct ibmebus_
                        unsigned long irq_flags, const char * devname,
                        void *dev_id)
  {
-       unsigned int irq = irq_create_mapping(NULL, ist, 0);
+       unsigned int irq = irq_create_mapping(NULL, ist);
        
        if (irq == NO_IRQ)
                return -EINVAL;
@@@ -11,6 -11,7 +11,7 @@@
  #include <linux/sched.h>
  #include <linux/errno.h>
  #include <linux/bootmem.h>
+ #include <linux/irq.h>
  
  #include <asm/processor.h>
  #include <asm/io.h>
@@@ -18,7 -19,6 +19,6 @@@
  #include <asm/sections.h>
  #include <asm/pci-bridge.h>
  #include <asm/byteorder.h>
- #include <asm/irq.h>
  #include <asm/uaccess.h>
  #include <asm/machdep.h>
  
@@@ -633,12 -633,12 +633,12 @@@ pcibios_alloc_controller(void
  static void
  make_one_node_map(struct device_node* node, u8 pci_bus)
  {
 -      int *bus_range;
 +      const int *bus_range;
        int len;
  
        if (pci_bus >= pci_bus_count)
                return;
 -      bus_range = (int *) get_property(node, "bus-range", &len);
 +      bus_range = get_property(node, "bus-range", &len);
        if (bus_range == NULL || len < 2 * sizeof(int)) {
                printk(KERN_WARNING "Can't get bus-range for %s, "
                       "assuming it starts at 0\n", node->full_name);
  
        for (node=node->child; node != 0;node = node->sibling) {
                struct pci_dev* dev;
 -              unsigned int *class_code, *reg;
 +              const unsigned int *class_code, *reg;
        
 -              class_code = (unsigned int *) get_property(node, "class-code", NULL);
 +              class_code = get_property(node, "class-code", NULL);
                if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
                        (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
                        continue;
 -              reg = (unsigned int *)get_property(node, "reg", NULL);
 +              reg = get_property(node, "reg", NULL);
                if (!reg)
                        continue;
                dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
@@@ -669,7 -669,7 +669,7 @@@ pcibios_make_OF_bus_map(void
  {
        int i;
        struct pci_controller* hose;
 -      u8* of_prop_map;
 +      struct property *map_prop;
  
        pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
        if (!pci_to_OF_bus_map) {
                        continue;
                make_one_node_map(node, hose->first_busno);
        }
 -      of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
 -      if (of_prop_map)
 -              memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
 +      map_prop = of_find_property(find_path_device("/"),
 +                      "pci-OF-bus-map", NULL);
 +      if (map_prop) {
 +              BUG_ON(pci_bus_count > map_prop->length);
 +              memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
 +      }
  #ifdef DEBUG
        printk("PCI->OF bus map:\n");
        for (i=0; i<pci_bus_count; i++) {
@@@ -715,7 -712,7 +715,7 @@@ scan_OF_pci_childs(struct device_node* 
        struct device_node* sub_node;
  
        for (; node != 0;node = node->sibling) {
 -              unsigned int *class_code;
 +              const unsigned int *class_code;
        
                if (filter(node, data))
                        return node;
                 * a fake root for all functions of a multi-function device,
                 * we go down them as well.
                 */
 -              class_code = (unsigned int *) get_property(node, "class-code", NULL);
 +              class_code = get_property(node, "class-code", NULL);
                if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
                        (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
                        strcmp(node->name, "multifunc-device"))
  static int
  scan_OF_pci_childs_iterator(struct device_node* node, void* data)
  {
 -      unsigned int *reg;
 +      const unsigned int *reg;
        u8* fdata = (u8*)data;
        
 -      reg = (unsigned int *) get_property(node, "reg", NULL);
 +      reg = get_property(node, "reg", NULL);
        if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
                && ((reg[0] >> 16) & 0xff) == fdata[0])
                return 1;
@@@ -844,7 -841,7 +844,7 @@@ find_OF_pci_device_filter(struct device
  int
  pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
  {
 -      unsigned int *reg;
 +      const unsigned int *reg;
        struct pci_controller* hose;
        struct pci_dev* dev = NULL;
        
        if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
                        find_OF_pci_device_filter, (void *)node))
                return -ENODEV;
 -      reg = (unsigned int *) get_property(node, "reg", NULL);
 +      reg = get_property(node, "reg", NULL);
        if (!reg)
                return -ENODEV;
        *bus = (reg[0] >> 16) & 0xff;
@@@ -888,8 -885,8 +888,8 @@@ pci_process_bridge_OF_ranges(struct pci
                           struct device_node *dev, int primary)
  {
        static unsigned int static_lc_ranges[256] __initdata;
 -      unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
 -      unsigned int size;
 +      const unsigned int *dt_ranges;
 +      unsigned int *lc_ranges, *ranges, *prev, size;
        int rlen = 0, orig_rlen;
        int memno = 0;
        struct resource *res;
         * that can have more than 3 ranges, fortunately using contiguous
         * addresses -- BenH
         */
 -      dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
 +      dt_ranges = get_property(dev, "ranges", &rlen);
        if (!dt_ranges)
                return;
        /* Sanity check, though hopefully that never happens */
@@@ -1423,15 -1420,37 +1423,37 @@@ int pci_read_irq_line(struct pci_dev *p
  
        DBG("Try to map irq for %s...\n", pci_name(pci_dev));
  
+       /* Try to get a mapping from the device-tree */
        if (of_irq_map_pci(pci_dev, &oirq)) {
-               DBG(" -> failed !\n");
-               return -1;
-       }
+               u8 line, pin;
+               /* If that fails, lets fallback to what is in the config
+                * space and map that through the default controller. We
+                * also set the type to level low since that's what PCI
+                * interrupts are. If your platform does differently, then
+                * either provide a proper interrupt tree or don't use this
+                * function.
+                */
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+                       return -1;
+               if (pin == 0)
+                       return -1;
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+                   line == 0xff) {
+                       return -1;
+               }
+               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
  
-       DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-           oirq.size, oirq.specifier[0], oirq.controller->full_name);
+               virq = irq_create_mapping(NULL, line);
+               if (virq != NO_IRQ)
+                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
+                   oirq.size, oirq.specifier[0], oirq.controller->full_name);
  
-       virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size);
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+       }
        if(virq == NO_IRQ) {
                DBG(" -> failed to map !\n");
                return -1;
  #include <linux/mm.h>
  #include <linux/list.h>
  #include <linux/syscalls.h>
+ #include <linux/irq.h>
  
  #include <asm/processor.h>
  #include <asm/io.h>
  #include <asm/prom.h>
  #include <asm/pci-bridge.h>
  #include <asm/byteorder.h>
- #include <asm/irq.h>
  #include <asm/machdep.h>
  #include <asm/ppc-pci.h>
  
@@@ -185,6 -185,34 +185,6 @@@ static void __devinit pci_setup_pci_con
        spin_unlock(&hose_spinlock);
  }
  
 -static void add_linux_pci_domain(struct device_node *dev,
 -                               struct pci_controller *phb)
 -{
 -      struct property *of_prop;
 -      unsigned int size;
 -
 -      of_prop = (struct property *)
 -              get_property(dev, "linux,pci-domain", &size);
 -      if (of_prop != NULL)
 -              return;
 -      WARN_ON(of_prop && size < sizeof(int));
 -      if (of_prop && size < sizeof(int))
 -              of_prop = NULL;
 -      size = sizeof(struct property) + sizeof(int);
 -      if (of_prop == NULL) {
 -              if (mem_init_done)
 -                      of_prop = kmalloc(size, GFP_KERNEL);
 -              else
 -                      of_prop = alloc_bootmem(size);
 -      }
 -      memset(of_prop, 0, sizeof(struct property));
 -      of_prop->name = "linux,pci-domain";
 -      of_prop->length = sizeof(int);
 -      of_prop->value = (unsigned char *)&of_prop[1];
 -      *((int *)of_prop->value) = phb->global_number;
 -      prom_add_property(dev, of_prop);
 -}
 -
  struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
  {
        struct pci_controller *phb;
        pci_setup_pci_controller(phb);
        phb->arch_data = dev;
        phb->is_dynamic = mem_init_done;
 -      if (dev) {
 +      if (dev)
                PHB_SET_NODE(phb, of_node_to_nid(dev));
 -              add_linux_pci_domain(dev, phb);
 -      }
        return phb;
  }
  
  void pcibios_free_controller(struct pci_controller *phb)
  {
 -      if (phb->arch_data) {
 -              struct device_node *np = phb->arch_data;
 -              int *domain = (int *)get_property(np,
 -                                                "linux,pci-domain", NULL);
 -              if (domain)
 -                      *domain = -1;
 -      }
        if (phb->is_dynamic)
                kfree(phb);
  }
@@@ -246,10 -283,10 +246,10 @@@ static void __init pcibios_claim_of_set
  #ifdef CONFIG_PPC_MULTIPLATFORM
  static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
  {
 -      u32 *prop;
 +      const u32 *prop;
        int len;
  
 -      prop = (u32 *) get_property(np, name, &len);
 +      prop = get_property(np, name, &len);
        if (prop && len >= 4)
                return *prop;
        return def;
@@@ -278,11 -315,10 +278,11 @@@ static void pci_parse_of_addrs(struct d
        u64 base, size;
        unsigned int flags;
        struct resource *res;
 -      u32 *addrs, i;
 +      const u32 *addrs;
 +      u32 i;
        int proplen;
  
 -      addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
 +      addrs = get_property(node, "assigned-addresses", &proplen);
        if (!addrs)
                return;
        DBG("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
@@@ -382,7 -418,7 +382,7 @@@ void __devinit of_scan_bus(struct devic
                                  struct pci_bus *bus)
  {
        struct device_node *child = NULL;
 -      u32 *reg;
 +      const u32 *reg;
        int reglen, devfn;
        struct pci_dev *dev;
  
  
        while ((child = of_get_next_child(node, child)) != NULL) {
                DBG("  * %s\n", child->full_name);
 -              reg = (u32 *) get_property(child, "reg", &reglen);
 +              reg = get_property(child, "reg", &reglen);
                if (reg == NULL || reglen < 20)
                        continue;
                devfn = (reg[0] >> 8) & 0xff;
@@@ -414,7 -450,7 +414,7 @@@ void __devinit of_scan_pci_bridge(struc
                                struct pci_dev *dev)
  {
        struct pci_bus *bus;
 -      u32 *busrange, *ranges;
 +      const u32 *busrange, *ranges;
        int len, i, mode;
        struct resource *res;
        unsigned int flags;
        DBG("of_scan_pci_bridge(%s)\n", node->full_name);
  
        /* parse bus-range property */
 -      busrange = (u32 *) get_property(node, "bus-range", &len);
 +      busrange = get_property(node, "bus-range", &len);
        if (busrange == NULL || len != 8) {
                printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
                       node->full_name);
                return;
        }
 -      ranges = (u32 *) get_property(node, "ranges", &len);
 +      ranges = get_property(node, "ranges", &len);
        if (ranges == NULL) {
                printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
                       node->full_name);
@@@ -893,13 -929,13 +893,13 @@@ static void __devinit pci_process_ISA_O
                unsigned int size;
        };
  
 -      struct isa_range *range;
 +      const struct isa_range *range;
        unsigned long pci_addr;
        unsigned int isa_addr;
        unsigned int size;
        int rlen = 0;
  
 -      range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
 +      range = get_property(isa_node, "ranges", &rlen);
        if (range == NULL || (rlen < sizeof(struct isa_range))) {
                printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
                       "mapping 64k\n");
  void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
                                            struct device_node *dev, int prim)
  {
 -      unsigned int *ranges, pci_space;
 +      const unsigned int *ranges;
 +      unsigned int pci_space;
        unsigned long size;
        int rlen = 0;
        int memno = 0;
         *                      (size depending on dev->n_addr_cells)
         *   cells 4+5 or 5+6:  the size of the range
         */
 -      ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
 +      ranges = get_property(dev, "ranges", &rlen);
        if (ranges == NULL)
                return;
        hose->io_base_phys = 0;
@@@ -1254,15 -1289,37 +1254,37 @@@ int pci_read_irq_line(struct pci_dev *p
  
        DBG("Try to map irq for %s...\n", pci_name(pci_dev));
  
+       /* Try to get a mapping from the device-tree */
        if (of_irq_map_pci(pci_dev, &oirq)) {
-               DBG(" -> failed !\n");
-               return -1;
-       }
+               u8 line, pin;
+               /* If that fails, lets fallback to what is in the config
+                * space and map that through the default controller. We
+                * also set the type to level low since that's what PCI
+                * interrupts are. If your platform does differently, then
+                * either provide a proper interrupt tree or don't use this
+                * function.
+                */
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+                       return -1;
+               if (pin == 0)
+                       return -1;
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+                   line == 0xff) {
+                       return -1;
+               }
+               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
  
-       DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-           oirq.size, oirq.specifier[0], oirq.controller->full_name);
+               virq = irq_create_mapping(NULL, line);
+               if (virq != NO_IRQ)
+                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
+                   oirq.size, oirq.specifier[0], oirq.controller->full_name);
  
-       virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size);
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+       }
        if(virq == NO_IRQ) {
                DBG(" -> failed to map !\n");
                return -1;
@@@ -27,7 -27,7 +27,7 @@@
  
  /* Debug utility */
  #ifdef DEBUG
 -static void of_dump_addr(const char *s, u32 *addr, int na)
 +static void of_dump_addr(const char *s, const u32 *addr, int na)
  {
        printk("%s", s);
        while(na--)
@@@ -35,7 -35,7 +35,7 @@@
        printk("\n");
  }
  #else
 -static void of_dump_addr(const char *s, u32 *addr, int na) { }
 +static void of_dump_addr(const char *s, const u32 *addr, int na) { }
  #endif
  
  
@@@ -46,10 -46,9 +46,10 @@@ struct of_bus 
        int             (*match)(struct device_node *parent);
        void            (*count_cells)(struct device_node *child,
                                       int *addrc, int *sizec);
 -      u64             (*map)(u32 *addr, u32 *range, int na, int ns, int pna);
 +      u64             (*map)(u32 *addr, const u32 *range,
 +                              int na, int ns, int pna);
        int             (*translate)(u32 *addr, u64 offset, int na);
 -      unsigned int    (*get_flags)(u32 *addr);
 +      unsigned int    (*get_flags)(const u32 *addr);
  };
  
  
@@@ -66,8 -65,7 +66,8 @@@ static void of_bus_default_count_cells(
                *sizec = prom_n_size_cells(dev);
  }
  
 -static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
 +static u64 of_bus_default_map(u32 *addr, const u32 *range,
 +              int na, int ns, int pna)
  {
        u64 cp, s, da;
  
@@@ -95,7 -93,7 +95,7 @@@ static int of_bus_default_translate(u3
        return 0;
  }
  
 -static unsigned int of_bus_default_get_flags(u32 *addr)
 +static unsigned int of_bus_default_get_flags(const u32 *addr)
  {
        return IORESOURCE_MEM;
  }
@@@ -120,7 -118,7 +120,7 @@@ static void of_bus_pci_count_cells(stru
                *sizec = 2;
  }
  
 -static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
 +static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
  {
        u64 cp, s, da;
  
@@@ -145,7 -143,7 +145,7 @@@ static int of_bus_pci_translate(u32 *ad
        return of_bus_default_translate(addr + 1, offset, na - 1);
  }
  
 -static unsigned int of_bus_pci_get_flags(u32 *addr)
 +static unsigned int of_bus_pci_get_flags(const u32 *addr)
  {
        unsigned int flags = 0;
        u32 w = addr[0];
@@@ -180,7 -178,7 +180,7 @@@ static void of_bus_isa_count_cells(stru
                *sizec = 1;
  }
  
 -static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
 +static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
  {
        u64 cp, s, da;
  
@@@ -205,7 -203,7 +205,7 @@@ static int of_bus_isa_translate(u32 *ad
        return of_bus_default_translate(addr + 1, offset, na - 1);
  }
  
 -static unsigned int of_bus_isa_get_flags(u32 *addr)
 +static unsigned int of_bus_isa_get_flags(const u32 *addr)
  {
        unsigned int flags = 0;
        u32 w = addr[0];
@@@ -270,7 -268,7 +270,7 @@@ static int of_translate_one(struct devi
                            struct of_bus *pbus, u32 *addr,
                            int na, int ns, int pna)
  {
 -      u32 *ranges;
 +      const u32 *ranges;
        unsigned int rlen;
        int rone;
        u64 offset = OF_BAD_ADDR;
         * to translate addresses that aren't supposed to be translated in
         * the first place. --BenH.
         */
 -      ranges = (u32 *)get_property(parent, "ranges", &rlen);
 +      ranges = get_property(parent, "ranges", &rlen);
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
   * that can be mapped to a cpu physical address). This is not really specified
   * that way, but this is traditionally the way IBM at least do things
   */
 -u64 of_translate_address(struct device_node *dev, u32 *in_addr)
 +u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
  {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
  }
  EXPORT_SYMBOL(of_translate_address);
  
 -u32 *of_get_address(struct device_node *dev, int index, u64 *size,
 +const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
                    unsigned int *flags)
  {
 -      u32 *prop;
 +      const u32 *prop;
        unsigned int psize;
        struct device_node *parent;
        struct of_bus *bus;
                return NULL;
  
        /* Get "reg" or "assigned-addresses" property */
 -      prop = (u32 *)get_property(dev, bus->addresses, &psize);
 +      prop = get_property(dev, bus->addresses, &psize);
        if (prop == NULL)
                return NULL;
        psize /= 4;
  }
  EXPORT_SYMBOL(of_get_address);
  
 -u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
 +const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                        unsigned int *flags)
  {
 -      u32 *prop;
 +      const u32 *prop;
        unsigned int psize;
        struct device_node *parent;
        struct of_bus *bus;
                return NULL;
  
        /* Get "reg" or "assigned-addresses" property */
 -      prop = (u32 *)get_property(dev, bus->addresses, &psize);
 +      prop = get_property(dev, bus->addresses, &psize);
        if (prop == NULL)
                return NULL;
        psize /= 4;
  }
  EXPORT_SYMBOL(of_get_pci_address);
  
 -static int __of_address_to_resource(struct device_node *dev, u32 *addrp,
 +static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
                                    u64 size, unsigned int flags,
                                    struct resource *r)
  {
  int of_address_to_resource(struct device_node *dev, int index,
                           struct resource *r)
  {
 -      u32             *addrp;
 +      const u32       *addrp;
        u64             size;
        unsigned int    flags;
  
@@@ -532,7 -530,7 +532,7 @@@ EXPORT_SYMBOL_GPL(of_address_to_resourc
  int of_pci_address_to_resource(struct device_node *dev, int bar,
                               struct resource *r)
  {
 -      u32             *addrp;
 +      const u32       *addrp;
        u64             size;
        unsigned int    flags;
  
  }
  EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
  
 -void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
 +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
                unsigned long *busno, unsigned long *phys, unsigned long *size)
  {
 -      u32 *dma_window, cells;
 -      unsigned char *prop;
 +      const u32 *dma_window;
 +      u32 cells;
 +      const unsigned char *prop;
  
 -      dma_window = (u32 *)dma_window_prop;
 +      dma_window = dma_window_prop;
  
        /* busno is always one cell */
        *busno = *(dma_window++);
@@@ -579,13 -576,13 +579,13 @@@ static struct device_node *of_irq_dflt_
  static struct device_node *of_irq_find_parent(struct device_node *child)
  {
        struct device_node *p;
 -      phandle *parp;
 +      const phandle *parp;
  
        if (!of_node_get(child))
                return NULL;
  
        do {
 -              parp = (phandle *)get_property(child, "interrupt-parent", NULL);
 +              parp = get_property(child, "interrupt-parent", NULL);
                if (parp == NULL)
                        p = of_get_parent(child);
                else {
@@@ -647,11 -644,11 +647,11 @@@ void of_irq_map_init(unsigned int flags
  
  }
  
 -int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
 -                 struct of_irq *out_irq)
 +int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
 +              const u32 *addr, struct of_irq *out_irq)
  {
        struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
 -      u32 *tmp, *imap, *imask;
 +      const u32 *tmp, *imap, *imask;
        u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
        int imaplen, match, i;
  
         * is none, we are nice and just walk up the tree
         */
        do {
 -              tmp = (u32 *)get_property(ipar, "#interrupt-cells", NULL);
 +              tmp = get_property(ipar, "#interrupt-cells", NULL);
                if (tmp != NULL) {
                        intsize = *tmp;
                        break;
         */
        old = of_node_get(ipar);
        do {
 -              tmp = (u32 *)get_property(old, "#address-cells", NULL);
 +              tmp = get_property(old, "#address-cells", NULL);
                tnode = of_get_parent(old);
                of_node_put(old);
                old = tnode;
                }
  
                /* Now look for an interrupt-map */
 -              imap = (u32 *)get_property(ipar, "interrupt-map", &imaplen);
 +              imap = get_property(ipar, "interrupt-map", &imaplen);
                /* No interrupt map, check for an interrupt parent */
                if (imap == NULL) {
                        DBG(" -> no map, getting parent\n");
                imaplen /= sizeof(u32);
  
                /* Look for a mask */
 -              imask = (u32 *)get_property(ipar, "interrupt-map-mask", NULL);
 +              imask = get_property(ipar, "interrupt-map-mask", NULL);
  
                /* If we were passed no "reg" property and we attempt to parse
                 * an interrupt-map, then #address-cells must be 0.
                        /* Get #interrupt-cells and #address-cells of new
                         * parent
                         */
 -                      tmp = (u32 *)get_property(newpar, "#interrupt-cells",
 +                      tmp = get_property(newpar, "#interrupt-cells",
                                                  NULL);
                        if (tmp == NULL) {
                                DBG(" -> parent lacks #interrupt-cells !\n");
                                goto fail;
                        }
                        newintsize = *tmp;
 -                      tmp = (u32 *)get_property(newpar, "#address-cells",
 +                      tmp = get_property(newpar, "#address-cells",
                                                  NULL);
                        newaddrsize = (tmp == NULL) ? 0 : *tmp;
  
@@@ -820,14 -817,14 +820,14 @@@ EXPORT_SYMBOL_GPL(of_irq_map_raw)
  static int of_irq_map_oldworld(struct device_node *device, int index,
                               struct of_irq *out_irq)
  {
 -      u32 *ints;
 +      const u32 *ints;
        int intlen;
  
        /*
         * Old machines just have a list of interrupt numbers
         * and no interrupt-controller nodes.
         */
 -      ints = (u32 *) get_property(device, "AAPL,interrupts", &intlen);
 +      ints = get_property(device, "AAPL,interrupts", &intlen);
        if (ints == NULL)
                return -EINVAL;
        intlen /= sizeof(u32);
@@@ -852,8 -849,7 +852,8 @@@ static int of_irq_map_oldworld(struct d
  int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
  {
        struct device_node *p;
 -      u32 *intspec, *tmp, intsize, intlen, *addr;
 +      const u32 *intspec, *tmp, *addr;
 +      u32 intsize, intlen;
        int res;
  
        DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
                return of_irq_map_oldworld(device, index, out_irq);
  
        /* Get the interrupts property */
 -      intspec = (u32 *)get_property(device, "interrupts", &intlen);
 +      intspec = get_property(device, "interrupts", &intlen);
        if (intspec == NULL)
                return -EINVAL;
        intlen /= sizeof(u32);
  
        /* Get the reg property (if any) */
 -      addr = (u32 *)get_property(device, "reg", NULL);
 +      addr = get_property(device, "reg", NULL);
  
        /* Look for the interrupt parent. */
        p = of_irq_find_parent(device);
                return -EINVAL;
  
        /* Get size of interrupt specifier */
 -      tmp = (u32 *)get_property(p, "#interrupt-cells", NULL);
 +      tmp = get_property(p, "#interrupt-cells", NULL);
        if (tmp == NULL) {
                of_node_put(p);
                return -EINVAL;
        intsize = *tmp;
  
        /* Check index */
-       if (index * intsize >= intlen)
+       if ((index + 1) * intsize > intlen)
                return -EINVAL;
  
        /* Get new specifier and map it */
@@@ -26,7 -26,7 +26,7 @@@
  #include <linux/ioport.h>
  #include <linux/console.h>
  #include <linux/utsname.h>
- #include <linux/tty.h>
+ #include <linux/screen_info.h>
  #include <linux/root_dev.h>
  #include <linux/notifier.h>
  #include <linux/cpu.h>
@@@ -304,15 -304,16 +304,15 @@@ struct seq_operations cpuinfo_op = 
  void __init check_for_initrd(void)
  {
  #ifdef CONFIG_BLK_DEV_INITRD
 -      unsigned long *prop;
 +      const unsigned long *prop;
  
        DBG(" -> check_for_initrd()\n");
  
        if (of_chosen) {
 -              prop = (unsigned long *)get_property(of_chosen,
 -                              "linux,initrd-start", NULL);
 +              prop = get_property(of_chosen, "linux,initrd-start", NULL);
                if (prop != NULL) {
                        initrd_start = (unsigned long)__va(*prop);
 -                      prop = (unsigned long *)get_property(of_chosen,
 +                      prop = get_property(of_chosen,
                                        "linux,initrd-end", NULL);
                        if (prop != NULL) {
                                initrd_end = (unsigned long)__va(*prop);
@@@ -365,14 -366,15 +365,14 @@@ void __init smp_setup_cpu_maps(void
        int cpu = 0;
  
        while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
 -              int *intserv;
 +              const int *intserv;
                int j, len = sizeof(u32), nthreads = 1;
  
 -              intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s",
 -                                            &len);
 +              intserv = get_property(dn, "ibm,ppc-interrupt-server#s", &len);
                if (intserv)
                        nthreads = len / sizeof(int);
                else {
 -                      intserv = (int *) get_property(dn, "reg", NULL);
 +                      intserv = get_property(dn, "reg", NULL);
                        if (!intserv)
                                intserv = &cpu; /* assume logical == phys */
                }
        if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
            (dn = of_find_node_by_path("/rtas"))) {
                int num_addr_cell, num_size_cell, maxcpus;
 -              unsigned int *ireg;
 +              const unsigned int *ireg;
  
                num_addr_cell = prom_n_addr_cells(dn);
                num_size_cell = prom_n_size_cells(dn);
  
 -              ireg = (unsigned int *)
 -                      get_property(dn, "ibm,lrdr-capacity", NULL);
 +              ireg = get_property(dn, "ibm,lrdr-capacity", NULL);
  
                if (!ireg)
                        goto out;
@@@ -60,7 -60,7 +60,7 @@@ static int smt_snooze_cmdline
  static int __init smt_setup(void)
  {
        struct device_node *options;
 -      unsigned int *val;
 +      const unsigned int *val;
        unsigned int cpu;
  
        if (!cpu_has_feature(CPU_FTR_SMT))
@@@ -70,7 -70,8 +70,7 @@@
        if (!options)
                return -ENODEV;
  
 -      val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
 -                                         NULL);
 +      val = get_property(options, "ibm,smt-snooze-delay", NULL);
        if (!smt_snooze_cmdline && val) {
                for_each_possible_cpu(cpu)
                        per_cpu(smt_snooze_delay, cpu) = *val;
@@@ -277,7 -278,7 +277,7 @@@ static void unregister_cpu_online(unsig
  }
  #endif /* CONFIG_HOTPLUG_CPU */
  
- static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
                                      unsigned long action, void *hcpu)
  {
        unsigned int cpu = (unsigned int)(long)hcpu;
        return NOTIFY_OK;
  }
  
- static struct notifier_block __devinitdata sysfs_cpu_nb = {
+ static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
        .notifier_call  = sysfs_cpu_notify,
  };
  
@@@ -159,7 -159,7 +159,7 @@@ static void iic_request_ipi(int ipi, co
                if (iic_hosts[node] == NULL)
                        continue;
                virq = irq_create_mapping(iic_hosts[node],
-                                         iic_ipi_to_irq(ipi), 0);
+                                         iic_ipi_to_irq(ipi));
                if (virq == NO_IRQ) {
                        printk(KERN_ERR
                               "iic: failed to map IPI %s on node %d\n",
@@@ -197,7 -197,7 +197,7 @@@ static int iic_host_match(struct irq_ho
  }
  
  static int iic_host_map(struct irq_host *h, unsigned int virq,
-                       irq_hw_number_t hw, unsigned int flags)
+                       irq_hw_number_t hw)
  {
        if (hw < IIC_IRQ_IPI0)
                set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
@@@ -250,14 -250,15 +250,14 @@@ static int __init setup_iic(void
        struct resource r0, r1;
        struct irq_host *host;
        int found = 0;
 -      u32 *np;
 +      const u32 *np;
  
        for (dn = NULL;
             (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
                if (!device_is_compatible(dn,
                                     "IBM,CBEA-Internal-Interrupt-Controller"))
                        continue;
 -              np = (u32 *)get_property(dn, "ibm,interrupt-server-ranges",
 -                                       NULL);
 +              np = get_property(dn, "ibm,interrupt-server-ranges", NULL);
                if (np == NULL) {
                        printk(KERN_WARNING "IIC: CPU association not found\n");
                        of_node_put(dn);
@@@ -85,9 -85,6 +85,6 @@@ static void spider_unmask_irq(unsigned 
        struct spider_pic *pic = spider_virq_to_pic(virq);
        void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
  
-       /* We use no locking as we should be covered by the descriptor lock
-        * for access to invidual source configuration registers
-        */
        out_be32(cfg, in_be32(cfg) | 0x30000000u);
  }
  
@@@ -96,9 -93,6 +93,6 @@@ static void spider_mask_irq(unsigned in
        struct spider_pic *pic = spider_virq_to_pic(virq);
        void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
  
-       /* We use no locking as we should be covered by the descriptor lock
-        * for access to invidual source configuration registers
-        */
        out_be32(cfg, in_be32(cfg) & ~0x30000000u);
  }
  
@@@ -120,26 -114,14 +114,14 @@@ static void spider_ack_irq(unsigned in
        out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
  }
  
- static struct irq_chip spider_pic = {
-       .typename = " SPIDER   ",
-       .unmask = spider_unmask_irq,
-       .mask = spider_mask_irq,
-       .ack = spider_ack_irq,
- };
- static int spider_host_match(struct irq_host *h, struct device_node *node)
- {
-       struct spider_pic *pic = h->host_data;
-       return node == pic->of_node;
- }
- static int spider_host_map(struct irq_host *h, unsigned int virq,
-                       irq_hw_number_t hw, unsigned int flags)
+ static int spider_set_irq_type(unsigned int virq, unsigned int type)
  {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-       struct spider_pic *pic = h->host_data;
+       unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
+       struct spider_pic *pic = spider_virq_to_pic(virq);
+       unsigned int hw = irq_map[virq].hwirq;
        void __iomem *cfg = spider_get_irq_config(pic, hw);
-       int level = 0;
+       struct irq_desc *desc = get_irq_desc(virq);
+       u32 old_mask;
        u32 ic;
  
        /* Note that only level high is supported for most interrupts */
                break;
        case IRQ_TYPE_LEVEL_LOW:
                ic = 0x0;
-               level = 1;
                break;
        case IRQ_TYPE_LEVEL_HIGH:
        case IRQ_TYPE_NONE:
                ic = 0x1;
-               level = 1;
                break;
        default:
                return -EINVAL;
        }
  
+       /* Update irq_desc */
+       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+       desc->status |= type & IRQ_TYPE_SENSE_MASK;
+       if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+               desc->status |= IRQ_LEVEL;
        /* Configure the source. One gross hack that was there before and
         * that I've kept around is the priority to the BE which I set to
         * be the same as the interrupt source number. I don't know wether
         * that's supposed to make any kind of sense however, we'll have to
         * decide that, but for now, I'm not changing the behaviour.
         */
-       out_be32(cfg, (ic << 24) | (0x7 << 16) | (pic->node_id << 4) | 0xe);
+       old_mask = in_be32(cfg) & 0x30000000u;
+       out_be32(cfg, old_mask | (ic << 24) | (0x7 << 16) |
+                (pic->node_id << 4) | 0xe);
        out_be32(cfg + 4, (0x2 << 16) | (hw & 0xff));
  
-       if (level)
-               get_irq_desc(virq)->status |= IRQ_LEVEL;
+       return 0;
+ }
+ static struct irq_chip spider_pic = {
+       .typename = " SPIDER   ",
+       .unmask = spider_unmask_irq,
+       .mask = spider_mask_irq,
+       .ack = spider_ack_irq,
+       .set_type = spider_set_irq_type,
+ };
+ static int spider_host_match(struct irq_host *h, struct device_node *node)
+ {
+       struct spider_pic *pic = h->host_data;
+       return node == pic->of_node;
+ }
+ static int spider_host_map(struct irq_host *h, unsigned int virq,
+                       irq_hw_number_t hw)
+ {
        set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq);
+       /* Set default irq type */
+       set_irq_type(virq, IRQ_TYPE_NONE);
        return 0;
  }
  
@@@ -230,7 -240,7 +240,7 @@@ static void spider_irq_cascade(unsigne
  static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
  {
        unsigned int virq;
 -      u32 *imap, *tmp;
 +      const u32 *imap, *tmp;
        int imaplen, intsize, unit;
        struct device_node *iic;
        struct irq_host *iic_host;
  #endif
  
        /* Now do the horrible hacks */
 -      tmp = (u32 *)get_property(pic->of_node, "#interrupt-cells", NULL);
 +      tmp = get_property(pic->of_node, "#interrupt-cells", NULL);
        if (tmp == NULL)
                return NO_IRQ;
        intsize = *tmp;
 -      imap = (u32 *)get_property(pic->of_node, "interrupt-map", &imaplen);
 +      imap = get_property(pic->of_node, "interrupt-map", &imaplen);
        if (imap == NULL || imaplen < (intsize + 1))
                return NO_IRQ;
        iic = of_find_node_by_phandle(imap[intsize]);
        if (iic == NULL)
                return NO_IRQ;
        imap += intsize + 1;
 -      tmp = (u32 *)get_property(iic, "#interrupt-cells", NULL);
 +      tmp = get_property(iic, "#interrupt-cells", NULL);
        if (tmp == NULL)
                return NO_IRQ;
        intsize = *tmp;
        /* Assume unit is last entry of interrupt specifier */
        unit = imap[intsize - 1];
        /* Ok, we have a unit, now let's try to get the node */
 -      tmp = (u32 *)get_property(iic, "ibm,interrupt-server-ranges", NULL);
 +      tmp = get_property(iic, "ibm,interrupt-server-ranges", NULL);
        if (tmp == NULL) {
                of_node_put(iic);
                return NO_IRQ;
        if (iic_host == NULL)
                return NO_IRQ;
        /* Manufacture an IIC interrupt number of class 2 */
-       virq = irq_create_mapping(iic_host, 0x20 | unit, 0);
+       virq = irq_create_mapping(iic_host, 0x20 | unit);
        if (virq == NO_IRQ)
                printk(KERN_ERR "spider_pic: failed to map cascade !");
        return virq;
@@@ -488,10 -488,10 +488,10 @@@ int spu_irq_class_1_bottom(struct spu *
  
  static int __init find_spu_node_id(struct device_node *spe)
  {
 -      unsigned int *id;
 +      const unsigned int *id;
        struct device_node *cpu;
        cpu = spe->parent->parent;
 -      id = (unsigned int *)get_property(cpu, "node-id", NULL);
 +      id = get_property(cpu, "node-id", NULL);
        return id ? *id : 0;
  }
  
@@@ -500,7 -500,7 +500,7 @@@ static int __init cell_spuprop_present(
  {
        static DEFINE_MUTEX(add_spumem_mutex);
  
 -      struct address_prop {
 +      const struct address_prop {
                unsigned long address;
                unsigned int len;
        } __attribute__((packed)) *p;
        struct zone *zone;
        int ret;
  
 -      p = (void*)get_property(spe, prop, &proplen);
 +      p = get_property(spe, prop, &proplen);
        WARN_ON(proplen != sizeof (*p));
  
        start_pfn = p->address >> PAGE_SHIFT;
  static void __iomem * __init map_spe_prop(struct spu *spu,
                struct device_node *n, const char *name)
  {
 -      struct address_prop {
 +      const struct address_prop {
                unsigned long address;
                unsigned int len;
        } __attribute__((packed)) *prop;
  
 -      void *p;
 +      const void *p;
        int proplen;
        void* ret = NULL;
        int err = 0;
@@@ -570,22 -570,22 +570,22 @@@ static int __init spu_map_interrupts(st
  {
        struct irq_host *host;
        unsigned int isrc;
 -      u32 *tmp;
 +      const u32 *tmp;
  
        host = iic_get_irq_host(spu->node);
        if (host == NULL)
                return -ENODEV;
  
        /* Get the interrupt source from the device-tree */
 -      tmp = (u32 *)get_property(np, "isrc", NULL);
 +      tmp = get_property(np, "isrc", NULL);
        if (!tmp)
                return -ENODEV;
        spu->isrc = isrc = tmp[0];
  
        /* Now map interrupts of all 3 classes */
-       spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc, 0);
-       spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc, 0);
-       spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc, 0);
+       spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
+       spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
+       spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
  
        /* Right now, we only fail if class 2 failed */
        return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
  
  static int __init spu_map_device(struct spu *spu, struct device_node *node)
  {
 -      char *prop;
 +      const char *prop;
        int ret;
  
        ret = -ENODEV;
@@@ -99,7 -99,8 +99,7 @@@ static unsigned long maple_find_nvram_b
  static void maple_restart(char *cmd)
  {
        unsigned int maple_nvram_base;
 -      unsigned int maple_nvram_offset;
 -      unsigned int maple_nvram_command;
 +      const unsigned int *maple_nvram_offset, *maple_nvram_command;
        struct device_node *sp;
  
        maple_nvram_base = maple_find_nvram_base();
                printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
                goto fail;
        }
 -      maple_nvram_offset = *(unsigned int*) get_property(sp,
 -                      "restart-addr", NULL);
 -      maple_nvram_command = *(unsigned int*) get_property(sp,
 -                      "restart-value", NULL);
 +      maple_nvram_offset = get_property(sp, "restart-addr", NULL);
 +      maple_nvram_command = get_property(sp, "restart-value", NULL);
        of_node_put(sp);
  
        /* send command */
 -      outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
 +      outb_p(*maple_nvram_command, maple_nvram_base + *maple_nvram_offset);
        for (;;) ;
   fail:
        printk(KERN_EMERG "Maple: Manual Restart Required\n");
  static void maple_power_off(void)
  {
        unsigned int maple_nvram_base;
 -      unsigned int maple_nvram_offset;
 -      unsigned int maple_nvram_command;
 +      const unsigned int *maple_nvram_offset, *maple_nvram_command;
        struct device_node *sp;
  
        maple_nvram_base = maple_find_nvram_base();
                printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
                goto fail;
        }
 -      maple_nvram_offset = *(unsigned int*) get_property(sp,
 -                      "power-off-addr", NULL);
 -      maple_nvram_command = *(unsigned int*) get_property(sp,
 -                      "power-off-value", NULL);
 +      maple_nvram_offset = get_property(sp, "power-off-addr", NULL);
 +      maple_nvram_command = get_property(sp, "power-off-value", NULL);
        of_node_put(sp);
  
        /* send command */
 -      outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
 +      outb_p(*maple_nvram_command, maple_nvram_base + *maple_nvram_offset);
        for (;;) ;
   fail:
        printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
@@@ -205,7 -211,7 +205,7 @@@ static void __init maple_init_early(voi
  static void __init maple_init_IRQ(void)
  {
        struct device_node *root, *np, *mpic_node = NULL;
 -      unsigned int *opprop;
 +      const unsigned int *opprop;
        unsigned long openpic_addr = 0;
        int naddr, n, i, opplen, has_isus = 0;
        struct mpic *mpic;
         * in Maple device-tree where the type of the controller is
         * open-pic and not interrupt-controller
         */
-       for_each_node_by_type(np, "open-pic") {
-               mpic_node = np;
-               break;
-       }
+       for_each_node_by_type(np, "interrupt-controller")
+               if (device_is_compatible(np, "open-pic")) {
+                       mpic_node = np;
+                       break;
+               }
+       if (mpic_node == NULL)
+               for_each_node_by_type(np, "open-pic") {
+                       mpic_node = np;
+                       break;
+               }
        if (mpic_node == NULL) {
                printk(KERN_ERR
                       "Failed to locate the MPIC interrupt controller\n");
        /* Find address list in /platform-open-pic */
        root = of_find_node_by_path("/");
        naddr = prom_n_addr_cells(root);
 -      opprop = (unsigned int *) get_property(root, "platform-open-pic",
 -                                             &opplen);
 +      opprop = get_property(root, "platform-open-pic", &opplen);
        if (opprop != 0) {
                openpic_addr = of_read_number(opprop, naddr);
                has_isus = (opplen > naddr);
  
        /* XXX Maple specific bits */
        flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+       /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
+       flags |= MPIC_BIG_ENDIAN;
  
        /* Setup the openpic driver. More device-tree junks, we hard code no
         * ISUs for now. I'll have to revisit some stuffs with the folks doing
  #include <linux/kernel.h>
  #include <linux/fb.h>
  #include <linux/backlight.h>
+ #include <linux/adb.h>
+ #include <linux/pmu.h>
+ #include <asm/atomic.h>
  #include <asm/prom.h>
  #include <asm/backlight.h>
  
  #define OLD_BACKLIGHT_MAX 15
  
+ static void pmac_backlight_key_worker(void *data);
+ static void pmac_backlight_set_legacy_worker(void *data);
+ static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
+ static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL);
+ /* Although these variables are used in interrupt context, it makes no sense to
+  * protect them. No user is able to produce enough key events per second and
+  * notice the errors that might happen.
+  */
+ static int pmac_backlight_key_queued;
+ static int pmac_backlight_set_legacy_queued;
+ /* The via-pmu code allows the backlight to be grabbed, in which case the
+  * in-kernel control of the brightness needs to be disabled. This should
+  * only be used by really old PowerBooks.
+  */
+ static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
  /* Protect the pmac_backlight variable */
  DEFINE_MUTEX(pmac_backlight_mutex);
  
@@@ -38,8 -60,7 +60,8 @@@ int pmac_has_backlight_type(const char 
        struct device_node* bk_node = find_devices("backlight");
  
        if (bk_node) {
 -              char *prop = get_property(bk_node, "backlight-control", NULL);
 +              const char *prop = get_property(bk_node,
 +                              "backlight-control", NULL);
                if (prop && strncmp(prop, type, strlen(type)) == 0)
                        return 1;
        }
@@@ -72,8 -93,11 +94,11 @@@ int pmac_backlight_curve_lookup(struct 
        return level;
  }
  
- static void pmac_backlight_key(int direction)
+ static void pmac_backlight_key_worker(void *data)
  {
+       if (atomic_read(&kernel_backlight_disabled))
+               return;
        mutex_lock(&pmac_backlight_mutex);
        if (pmac_backlight) {
                struct backlight_properties *props;
                props = pmac_backlight->props;
  
                brightness = props->brightness +
-                       ((direction?-1:1) * (props->max_brightness / 15));
+                       ((pmac_backlight_key_queued?-1:1) *
+                        (props->max_brightness / 15));
  
                if (brightness < 0)
                        brightness = 0;
        mutex_unlock(&pmac_backlight_mutex);
  }
  
- void pmac_backlight_key_up()
+ /* This function is called in interrupt context */
+ void pmac_backlight_key(int direction)
  {
-       pmac_backlight_key(0);
+       if (atomic_read(&kernel_backlight_disabled))
+               return;
+       /* we can receive multiple interrupts here, but the scheduled work
+        * will run only once, with the last value
+        */
+       pmac_backlight_key_queued = direction;
+       schedule_work(&pmac_backlight_key_work);
  }
  
- void pmac_backlight_key_down()
- {
-       pmac_backlight_key(1);
- }
- int pmac_backlight_set_legacy_brightness(int brightness)
+ static int __pmac_backlight_set_legacy_brightness(int brightness)
  {
        int error = -ENXIO;
  
        return error;
  }
  
+ static void pmac_backlight_set_legacy_worker(void *data)
+ {
+       if (atomic_read(&kernel_backlight_disabled))
+               return;
+       __pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);
+ }
+ /* This function is called in interrupt context */
+ void pmac_backlight_set_legacy_brightness_pmu(int brightness) {
+       if (atomic_read(&kernel_backlight_disabled))
+               return;
+       pmac_backlight_set_legacy_queued = brightness;
+       schedule_work(&pmac_backlight_set_legacy_work);
+ }
+ int pmac_backlight_set_legacy_brightness(int brightness)
+ {
+       return __pmac_backlight_set_legacy_brightness(brightness);
+ }
  int pmac_backlight_get_legacy_brightness()
  {
        int result = -ENXIO;
  
        return result;
  }
+ void pmac_backlight_disable()
+ {
+       atomic_inc(&kernel_backlight_disabled);
+ }
+ void pmac_backlight_enable()
+ {
+       atomic_dec(&kernel_backlight_disabled);
+ }
+ EXPORT_SYMBOL_GPL(pmac_backlight);
+ EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
+ EXPORT_SYMBOL_GPL(pmac_has_backlight_type);
@@@ -87,9 -87,9 +87,9 @@@ static int (*g5_query_freq)(void)
  static DEFINE_MUTEX(g5_switch_mutex);
  
  
- #ifdef CONFIG_PPC_SMU
+ #ifdef CONFIG_PMAC_SMU
  
- static const u32 *g5_pmode_data;
+ static u32 *g5_pmode_data;
  static int g5_pmode_max;
  
  static struct smu_sdbp_fvt *g5_fvt_table;     /* table of op. points */
@@@ -216,7 -216,7 +216,7 @@@ static void g5_dummy_switch_volt(int sp
  {
  }
  
- #endif /* CONFIG_PPC_SMU */
+ #endif /* CONFIG_PMAC_SMU */
  
  /*
   * Platform function based voltage switching for PowerMac7,2 & 7,3
@@@ -383,7 -383,7 +383,7 @@@ static struct cpufreq_driver g5_cpufreq
  };
  
  
- #ifdef CONFIG_PPC_SMU
+ #ifdef CONFIG_PMAC_SMU
  
  static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
  {
        unsigned int psize, ssize;
        unsigned long max_freq;
        char *freq_method, *volt_method;
 -      u32 *valp, pvr_hi;
 +      const u32 *valp;
 +      u32 pvr_hi;
        int use_volts_vdnap = 0;
        int use_volts_smu = 0;
        int rc = -ENODEV;
        /* Get first CPU node */
        for (cpunode = NULL;
             (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
 -              u32 *reg =
 -                      (u32 *)get_property(cpunode, "reg", NULL);
 +              const u32 *reg = get_property(cpunode, "reg", NULL);
                if (reg == NULL || (*reg) != 0)
                        continue;
                if (!strcmp(cpunode->type, "cpu"))
        }
  
        /* Check 970FX for now */
 -      valp = (u32 *)get_property(cpunode, "cpu-version", NULL);
 +      valp = get_property(cpunode, "cpu-version", NULL);
        if (!valp) {
                DBG("No cpu-version property !\n");
                goto bail_noprops;
        }
  
        /* Look for the powertune data in the device-tree */
 -      g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize);
 +      g5_pmode_data = get_property(cpunode, "power-mode-data",&psize);
        if (!g5_pmode_data) {
                DBG("No power-mode-data !\n");
                goto bail_noprops;
        g5_pmode_max = psize / sizeof(u32) - 1;
  
        if (use_volts_smu) {
 -              struct smu_sdbp_header *shdr;
 +              const struct smu_sdbp_header *shdr;
  
                /* Look for the FVT table */
                shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
         * half freq in this version. So far, I haven't yet seen a machine
         * supporting anything else.
         */
 -      valp = (u32 *)get_property(cpunode, "clock-frequency", NULL);
 +      valp = get_property(cpunode, "clock-frequency", NULL);
        if (!valp)
                return -ENODEV;
        max_freq = (*valp)/1000;
        return rc;
  }
  
- #endif /* CONFIG_PPC_SMU */
+ #endif /* CONFIG_PMAC_SMU */
  
  
  static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
  {
        struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
 -      u8 *eeprom = NULL;
 -      u32 *valp;
 +      const u8 *eeprom = NULL;
 +      const u32 *valp;
        u64 max_freq, min_freq, ih, il;
        int has_volt = 1, rc = 0;
  
        /* Lookup the cpuid eeprom node */
          cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0");
        if (cpuid != NULL)
 -              eeprom = (u8 *)get_property(cpuid, "cpuid", NULL);
 +              eeprom = get_property(cpuid, "cpuid", NULL);
        if (eeprom == NULL) {
                printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n");
                rc = -ENODEV;
        /* Lookup the i2c hwclock */
        for (hwclock = NULL;
             (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){
 -              char *loc = get_property(hwclock, "hwctrl-location", NULL);
 +              const char *loc = get_property(hwclock,
 +                              "hwctrl-location", NULL);
                if (loc == NULL)
                        continue;
                if (strcmp(loc, "CPU CLOCK"))
         */
  
        /* Get max frequency from device-tree */
 -      valp = (u32 *)get_property(cpunode, "clock-frequency", NULL);
 +      valp = get_property(cpunode, "clock-frequency", NULL);
        if (!valp) {
                printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n");
                rc = -ENODEV;
@@@ -731,10 -730,10 +731,10 @@@ static int __init g5_cpufreq_init(void
            machine_is_compatible("PowerMac7,3") ||
            machine_is_compatible("RackMac3,1"))
                rc = g5_pm72_cpufreq_init(cpus);
- #ifdef CONFIG_PPC_SMU
+ #ifdef CONFIG_PMAC_SMU
        else
                rc = g5_neo2_cpufreq_init(cpus);
- #endif /* CONFIG_PPC_SMU */
+ #endif /* CONFIG_PMAC_SMU */
  
        of_node_put(cpus);
        return rc;
@@@ -16,6 -16,7 +16,7 @@@
  #include <linux/string.h>
  #include <linux/init.h>
  #include <linux/bootmem.h>
+ #include <linux/irq.h>
  
  #include <asm/sections.h>
  #include <asm/io.h>
  #include <asm/machdep.h>
  #include <asm/pmac_feature.h>
  #include <asm/grackle.h>
- #ifdef CONFIG_PPC64
- //#include <asm/iommu.h>
  #include <asm/ppc-pci.h>
- #endif
  
  #undef DEBUG
  
@@@ -46,7 -44,6 +44,6 @@@ static int has_uninorth
  static struct pci_controller *u3_agp;
  static struct pci_controller *u4_pcie;
  static struct pci_controller *u3_ht;
- #define has_second_ohare 0
  #else
  static int has_second_ohare;
  #endif /* CONFIG_PPC64 */
@@@ -69,16 -66,16 +66,16 @@@ struct device_node *k2_skiplist[2]
  static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
  {
        for (; node != 0;node = node->sibling) {
 -              int * bus_range;
 -              unsigned int *class_code;
 +              const int * bus_range;
 +              const unsigned int *class_code;
                int len;
  
                /* For PCI<->PCI bridges or CardBus bridges, we go down */
 -              class_code = (unsigned int *) get_property(node, "class-code", NULL);
 +              class_code = get_property(node, "class-code", NULL);
                if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
                        (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
                        continue;
 -              bus_range = (int *) get_property(node, "bus-range", &len);
 +              bus_range = get_property(node, "bus-range", &len);
                if (bus_range != NULL && len > 2 * sizeof(int)) {
                        if (bus_range[1] > higher)
                                higher = bus_range[1];
   */
  static void __init fixup_bus_range(struct device_node *bridge)
  {
 -      int * bus_range;
 -      int len;
 +      int *bus_range, len;
 +      struct property *prop;
  
        /* Lookup the "bus-range" property for the hose */
 -      bus_range = (int *) get_property(bridge, "bus-range", &len);
 -      if (bus_range == NULL || len < 2 * sizeof(int))
 +      prop = of_find_property(bridge, "bus-range", &len);
 +      if (prop == NULL || prop->length < 2 * sizeof(int))
                return;
 +
 +      bus_range = (int *)prop->value;
        bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
  }
  
@@@ -242,7 -237,7 +239,7 @@@ static struct pci_ops macrisc_pci_ops 
  static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
  {
        struct device_node *np;
 -      u32 *vendor, *device;
 +      const u32 *vendor, *device;
  
        if (offset >= 0x100)
                return  PCIBIOS_BAD_REGISTER_NUMBER;
        if (np == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
  
 -      vendor = (u32 *)get_property(np, "vendor-id", NULL);
 -      device = (u32 *)get_property(np, "device-id", NULL);
 +      vendor = get_property(np, "vendor-id", NULL);
 +      device = get_property(np, "device-id", NULL);
        if (vendor == NULL || device == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
  
@@@ -691,21 -686,20 +688,21 @@@ static void __init fixup_nec_usb2(void
  
        for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
                struct pci_controller *hose;
 -              u32 data, *prop;
 +              u32 data;
 +              const u32 *prop;
                u8 bus, devfn;
  
 -              prop = (u32 *)get_property(nec, "vendor-id", NULL);
 +              prop = get_property(nec, "vendor-id", NULL);
                if (prop == NULL)
                        continue;
                if (0x1033 != *prop)
                        continue;
 -              prop = (u32 *)get_property(nec, "device-id", NULL);
 +              prop = get_property(nec, "device-id", NULL);
                if (prop == NULL)
                        continue;
                if (0x0035 != *prop)
                        continue;
 -              prop = (u32 *)get_property(nec, "reg", NULL);
 +              prop = get_property(nec, "reg", NULL);
                if (prop == NULL)
                        continue;
                devfn = (prop[0] >> 8) & 0xff;
@@@ -904,7 -898,7 +901,7 @@@ static int __init add_bridge(struct dev
        struct pci_controller *hose;
        struct resource rsrc;
        char *disp_name;
 -      int *bus_range;
 +      const int *bus_range;
        int primary = 1, has_address = 0;
  
        DBG("Adding PCI host bridge %s\n", dev->full_name);
        has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
  
        /* Get bus range if any */
 -      bus_range = (int *) get_property(dev, "bus-range", &len);
 +      bus_range = get_property(dev, "bus-range", &len);
        if (bus_range == NULL || len < 2 * sizeof(int)) {
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                       " bus 0\n", dev->full_name);
@@@ -996,6 -990,7 +993,7 @@@ void __init pmac_pcibios_fixup(void
                /* Read interrupt from the device-tree */
                pci_read_irq_line(dev);
  
+ #ifdef CONFIG_PPC32
                /* Fixup interrupt for the modem/ethernet combo controller.
                 * on machines with a second ohare chip.
                 * The number in the device tree (27) is bogus (correct for
                 */
                if (has_second_ohare &&
                    dev->vendor == PCI_VENDOR_ID_DEC &&
-                   dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS)
-                       dev->irq = irq_create_mapping(NULL, 60, 0);
+                   dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
+                       dev->irq = irq_create_mapping(NULL, 60);
+                       set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+               }
+ #endif /* CONFIG_PPC32 */
        }
  }
  
@@@ -79,7 -79,7 +79,7 @@@ static void request_ras_irqs(struct dev
  {
        int i, index, count = 0;
        struct of_irq oirq;
 -      u32 *opicprop;
 +      const u32 *opicprop;
        unsigned int opicplen;
        unsigned int virqs[16];
  
         * map those interrupts using the default interrupt host and default
         * trigger
         */
 -      opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen);
 +      opicprop = get_property(np, "open-pic-interrupt", &opicplen);
        if (opicprop) {
                opicplen /= sizeof(u32);
                for (i = 0; i < opicplen; i++) {
                        if (count > 15)
                                break;
-                       virqs[count] = irq_create_mapping(NULL, *(opicprop++),
-                                                        IRQ_TYPE_NONE);
+                       virqs[count] = irq_create_mapping(NULL, *(opicprop++));
                        if (virqs[count] == NO_IRQ)
                                printk(KERN_ERR "Unable to allocate interrupt "
                                       "number for %s\n", np->full_name);
@@@ -133,9 -133,9 +133,9 @@@ void pseries_8259_cascade(unsigned int 
  static void __init pseries_mpic_init_IRQ(void)
  {
        struct device_node *np, *old, *cascade = NULL;
 -        unsigned int *addrp;
 +        const unsigned int *addrp;
        unsigned long intack = 0;
 -      unsigned int *opprop;
 +      const unsigned int *opprop;
        unsigned long openpic_addr = 0;
        unsigned int cascade_irq;
        int naddr, n, i, opplen;
  
        np = of_find_node_by_path("/");
        naddr = prom_n_addr_cells(np);
 -      opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen);
 +      opprop = get_property(np, "platform-open-pic", &opplen);
        if (opprop != 0) {
                openpic_addr = of_read_number(opprop, naddr);
                printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
                        break;
                if (strcmp(np->name, "pci") != 0)
                        continue;
 -              addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge",
 +              addrp = get_property(np, "8259-interrupt-acknowledge",
                                            NULL);
                if (addrp == NULL)
                        continue;
@@@ -249,11 -249,11 +249,11 @@@ static void pseries_kexec_cpu_down_xics
  static void __init pseries_discover_pic(void)
  {
        struct device_node *np;
 -      char *typep;
 +      const char *typep;
  
        for (np = NULL; (np = of_find_node_by_name(np,
                                                   "interrupt-controller"));) {
 -              typep = (char *)get_property(np, "compatible", NULL);
 +              typep = get_property(np, "compatible", NULL);
                if (strstr(typep, "open-pic")) {
                        pSeries_mpic_node = of_node_get(np);
                        ppc_md.init_IRQ       = pseries_mpic_init_IRQ;
@@@ -501,7 -501,8 +501,8 @@@ static void pseries_dedicated_idle_slee
        }
  
        /*
-        * Cede if the other thread is not idle, so that it can
+        * If not SMT, cede processor.  If CPU is running SMT
+        * cede if the other thread is not idle, so that it can
         * go single-threaded.  If the other thread is idle,
         * we ask the hypervisor if it has pending work it
         * wants to do and cede if it does.  Otherwise we keep
         * very low priority.  The cede enables interrupts, which
         * doesn't matter here.
         */
-       if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+       if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
+           || poll_pending() == H_PENDING)
                cede_processor();
  
  out:
@@@ -502,16 -502,9 +502,9 @@@ static int xics_host_match(struct irq_h
  }
  
  static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
-                               irq_hw_number_t hw, unsigned int flags)
+                               irq_hw_number_t hw)
  {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-       pr_debug("xics: map_direct virq %d, hwirq 0x%lx, flags: 0x%x\n",
-                virq, hw, flags);
-       if (sense && sense != IRQ_TYPE_LEVEL_LOW)
-               printk(KERN_WARNING "xics: using unsupported sense 0x%x"
-                      " for irq %d (h: 0x%lx)\n", flags, virq, hw);
+       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
  
        get_irq_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
  }
  
  static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
-                             irq_hw_number_t hw, unsigned int flags)
+                             irq_hw_number_t hw)
  {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-       pr_debug("xics: map_lpar virq %d, hwirq 0x%lx, flags: 0x%x\n",
-                virq, hw, flags);
-       if (sense && sense != IRQ_TYPE_LEVEL_LOW)
-               printk(KERN_WARNING "xics: using unsupported sense 0x%x"
-                      " for irq %d (h: 0x%lx)\n", flags, virq, hw);
+       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
  
        get_irq_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
@@@ -604,14 -590,14 +590,14 @@@ static void __init xics_init_one_node(s
                                      unsigned int *indx)
  {
        unsigned int ilen;
 -      u32 *ireg;
 +      const u32 *ireg;
  
        /* This code does the theorically broken assumption that the interrupt
         * server numbers are the same as the hard CPU numbers.
         * This happens to be the case so far but we are playing with fire...
         * should be fixed one of these days. -BenH.
         */
 -      ireg = (u32 *)get_property(np, "ibm,interrupt-server-ranges", NULL);
 +      ireg = get_property(np, "ibm,interrupt-server-ranges", NULL);
  
        /* Do that ever happen ? we'll know soon enough... but even good'old
         * f80 does have that property ..
                 */
                *indx = *ireg;
        }
 -      ireg = (u32 *)get_property(np, "reg", &ilen);
 +      ireg = get_property(np, "reg", &ilen);
        if (!ireg)
                panic("xics_init_IRQ: can't find interrupt reg property");
  
@@@ -649,7 -635,7 +635,7 @@@ static void __init xics_setup_8259_casc
  {
        struct device_node *np, *old, *found = NULL;
        int cascade, naddr;
 -      u32 *addrp;
 +      const u32 *addrp;
        unsigned long intack = 0;
  
        for_each_node_by_type(np, "interrupt-controller")
                        break;
                if (strcmp(np->name, "pci") != 0)
                        continue;
 -              addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL);
 +              addrp = get_property(np, "8259-interrupt-acknowledge", NULL);
                if (addrp == NULL)
                        continue;
                naddr = prom_n_addr_cells(np);
@@@ -694,8 -680,7 +680,8 @@@ void __init xics_init_IRQ(void
  {
        int i;
        struct device_node *np;
 -      u32 *ireg, ilen, indx = 0;
 +      u32 ilen, indx = 0;
 +      const u32 *ireg;
        int found = 0;
  
        ppc64_boot_msg(0x20, "XICS Init");
        for (np = of_find_node_by_type(NULL, "cpu");
             np;
             np = of_find_node_by_type(np, "cpu")) {
 -              ireg = (u32 *)get_property(np, "reg", &ilen);
 +              ireg = get_property(np, "reg", &ilen);
                if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
 -                      ireg = (u32 *)get_property(np,
 -                                                "ibm,ppc-interrupt-gserver#s",
 -                                                 &ilen);
 +                      ireg = get_property(np,
 +                                      "ibm,ppc-interrupt-gserver#s", &ilen);
                        i = ilen / sizeof(int);
                        if (ireg && i > 0) {
                                default_server = ireg[0];
                                /* take last element */
                                default_distrib_server = ireg[i-1];
                        }
 -                      ireg = (u32 *)get_property(np,
 +                      ireg = get_property(np,
                                        "ibm,interrupt-server#-size", NULL);
                        if (ireg)
                                interrupt_server_size = *ireg;
@@@ -757,7 -743,7 +743,7 @@@ void xics_request_IPIs(void
  {
        unsigned int ipi;
  
-       ipi = irq_create_mapping(xics_host, XICS_IPI, 0);
+       ipi = irq_create_mapping(xics_host, XICS_IPI);
        BUG_ON(ipi == NO_IRQ);
  
        /*
@@@ -783,6 -769,14 +769,14 @@@ void xics_teardown_cpu(int secondary
        xics_set_cpu_priority(cpu, 0);
  
        /*
+        * Clear IPI
+        */
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_qirr_info(cpu, 0xff);
+       else
+               direct_qirr_info(cpu, 0xff);
+       /*
         * we need to EOI the IPI if we got here from kexec down IPI
         *
         * probably need to check all the other interrupts too
                return;
        desc = get_irq_desc(ipi);
        if (desc->chip && desc->chip->eoi)
-               desc->chip->eoi(XICS_IPI);
+               desc->chip->eoi(ipi);
  
        /*
         * Some machines need to have at least one cpu in the GIQ,
diff --combined drivers/char/hvsi.c
@@@ -1276,10 -1276,11 +1276,10 @@@ static int __init hvsi_console_init(voi
                        vty != NULL;
                        vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) {
                struct hvsi_struct *hp;
 -              uint32_t *vtermno;
 -              uint32_t *irq;
 +              const uint32_t *vtermno, *irq;
  
 -              vtermno = (uint32_t *)get_property(vty, "reg", NULL);
 -              irq = (uint32_t *)get_property(vty, "interrupts", NULL);
 +              vtermno = get_property(vty, "reg", NULL);
 +              irq = get_property(vty, "interrupts", NULL);
                if (!vtermno || !irq)
                        continue;
  
                hp->inbuf_end = hp->inbuf;
                hp->state = HVSI_CLOSED;
                hp->vtermno = *vtermno;
-               hp->virq = irq_create_mapping(NULL, irq[0], 0);
+               hp->virq = irq_create_mapping(NULL, irq[0]);
                if (hp->virq == NO_IRQ) {
                        printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
                                __FUNCTION__, irq[0]);
@@@ -148,8 -148,6 +148,6 @@@ static int i2c_powermac_master_xfer(       st
        int                     read;
        int                     addrdir;
  
-       if (num != 1)
-               return -EINVAL;
        if (msgs->flags & I2C_M_TEN)
                return -EINVAL;
        read = (msgs->flags & I2C_M_RD) != 0;
        rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
   bail:
        pmac_i2c_close(bus);
-       return rc < 0 ? rc : msgs->len;
+       return rc < 0 ? rc : 1;
  }
  
  static u32 i2c_powermac_func(struct i2c_adapter * adapter)
@@@ -209,8 -207,7 +207,8 @@@ static int i2c_powermac_probe(struct de
        struct pmac_i2c_bus *bus = dev->platform_data;
        struct device_node *parent = NULL;
        struct i2c_adapter *adapter;
 -      char name[32], *basename;
 +      char name[32];
 +      const char *basename;
        int rc;
  
        if (bus == NULL)
@@@ -139,9 -139,7 +139,9 @@@ static int macio_uevent(struct device *
  {
        struct macio_dev * macio_dev;
        struct of_device * of;
 -      char *scratch, *compat, *compat2;
 +      char *scratch;
 +      const char *compat, *compat2;
 +
        int i = 0;
        int length, cplen, cplen2, seen = 0;
  
           * it's not really legal to split it out with commas. We split it
           * up using a number of environment variables instead. */
  
 -      compat = (char *) get_property(of->node, "compatible", &cplen);
 +      compat = get_property(of->node, "compatible", &cplen);
        compat2 = compat;
        cplen2= cplen;
        while (compat && cplen > 0) {
@@@ -332,7 -330,7 +332,7 @@@ static void macio_create_fixup_irq(stru
  {
        unsigned int irq;
  
-       irq = irq_create_mapping(NULL, line, 0);
+       irq = irq_create_mapping(NULL, line);
        if (irq != NO_IRQ) {
                dev->interrupt[index].start = irq;
                dev->interrupt[index].flags = IORESOURCE_IRQ;
@@@ -456,7 -454,7 +456,7 @@@ static struct macio_dev * macio_add_one
                                               struct resource *parent_res)
  {
        struct macio_dev *dev;
 -      u32 *reg;
 +      const u32 *reg;
        
        if (np == NULL)
                return NULL;
  #endif
                        MAX_NODE_NAME_SIZE, np->name);
        } else {
 -              reg = (u32 *)get_property(np, "reg", NULL);
 +              reg = get_property(np, "reg", NULL);
                sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
                        chip->lbus.index,
                        reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
diff --combined drivers/macintosh/smu.c
@@@ -75,9 -75,11 +75,11 @@@ struct smu_device 
        struct of_device        *of_dev;
        int                     doorbell;       /* doorbell gpio */
        u32 __iomem             *db_buf;        /* doorbell buffer */
-       int                     db_irq;
+       struct device_node      *db_node;
+       unsigned int            db_irq;
        int                     msg;
-       int                     msg_irq;
+       struct device_node      *msg_node;
+       unsigned int            msg_irq;
        struct smu_cmd_buf      *cmd_buf;       /* command buffer virtual */
        u32                     cmd_buf_abs;    /* command buffer absolute */
        struct list_head        cmd_list;
@@@ -93,6 -95,7 +95,7 @@@
   */
  static struct smu_device      *smu;
  static DEFINE_MUTEX(smu_part_access);
+ static int smu_irq_inited;
  
  static void smu_i2c_retry(unsigned long data);
  
@@@ -257,6 -260,10 +260,10 @@@ int smu_queue_cmd(struct smu_cmd *cmd
                smu_start_cmd();
        spin_unlock_irqrestore(&smu->lock, flags);
  
+       /* Workaround for early calls when irq isn't available */
+       if (!smu_irq_inited || smu->db_irq == NO_IRQ)
+               smu_spinwait_cmd(cmd);
        return 0;
  }
  EXPORT_SYMBOL(smu_queue_cmd);
@@@ -447,7 -454,7 +454,7 @@@ EXPORT_SYMBOL(smu_present)
  int __init smu_init (void)
  {
        struct device_node *np;
 -      u32 *data;
 +      const u32 *data;
  
          np = of_find_node_by_type(NULL, "smu");
          if (np == NULL)
        smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
        smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
  
-       np = of_find_node_by_name(NULL, "smu-doorbell");
-       if (np == NULL) {
+       smu->db_node = of_find_node_by_name(NULL, "smu-doorbell");
+       if (smu->db_node == NULL) {
                printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
                goto fail;
        }
-       data = get_property(np, "reg", NULL);
 -      data = (u32 *)get_property(smu->db_node, "reg", NULL);
++      data = get_property(smu->db_node, "reg", NULL);
        if (data == NULL) {
-               of_node_put(np);
+               of_node_put(smu->db_node);
+               smu->db_node = NULL;
                printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
                goto fail;
        }
        smu->doorbell = *data;
        if (smu->doorbell < 0x50)
                smu->doorbell += 0x50;
  
        /* Now look for the smu-interrupt GPIO */
        do {
-               np = of_find_node_by_name(NULL, "smu-interrupt");
-               if (np == NULL)
+               smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt");
+               if (smu->msg_node == NULL)
                        break;
-               data = get_property(np, "reg", NULL);
 -              data = (u32 *)get_property(smu->msg_node, "reg", NULL);
++              data = get_property(smu->msg_node, "reg", NULL);
                if (data == NULL) {
-                       of_node_put(np);
+                       of_node_put(smu->msg_node);
+                       smu->msg_node = NULL;
                        break;
                }
                smu->msg = *data;
                if (smu->msg < 0x50)
                        smu->msg += 0x50;
-               smu->msg_irq = irq_of_parse_and_map(np, 0);
-               of_node_put(np);
        } while(0);
  
        /* Doorbell buffer is currently hard-coded, I didn't find a proper
@@@ -547,6 -551,19 +551,19 @@@ static int smu_late_init(void
        smu->i2c_timer.function = smu_i2c_retry;
        smu->i2c_timer.data = (unsigned long)smu;
  
+       if (smu->db_node) {
+               smu->db_irq = irq_of_parse_and_map(smu->db_node, 0);
+               if (smu->db_irq == NO_IRQ)
+                       printk(KERN_ERR "smu: failed to map irq for node %s\n",
+                              smu->db_node->full_name);
+       }
+       if (smu->msg_node) {
+               smu->msg_irq = irq_of_parse_and_map(smu->msg_node, 0);
+               if (smu->msg_irq == NO_IRQ)
+                       printk(KERN_ERR "smu: failed to map irq for node %s\n",
+                              smu->msg_node->full_name);
+       }
        /*
         * Try to request the interrupts
         */
                }
        }
  
+       smu_irq_inited = 1;
        return 0;
  }
  /* This has to be before arch_initcall as the low i2c stuff relies on the
@@@ -742,6 -760,11 +760,11 @@@ static void smu_i2c_low_completion(stru
        if (fail && --cmd->retries > 0) {
                DPRINTK("SMU: i2c failure, starting timer...\n");
                BUG_ON(cmd != smu->cmd_i2c_cur);
+               if (!smu_irq_inited) {
+                       mdelay(5);
+                       smu_i2c_retry(0);
+                       return;
+               }
                mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
                return;
        }
@@@ -959,11 -982,11 +982,11 @@@ static struct smu_sdbp_header *smu_crea
  /* Note: Only allowed to return error code in pointers (using ERR_PTR)
   * when interruptible is 1
   */
 -struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
 -                                              int interruptible)
 +const struct smu_sdbp_header *__smu_get_sdb_partition(int id,
 +              unsigned int *size, int interruptible)
  {
        char pname[32];
 -      struct smu_sdbp_header *part;
 +      const struct smu_sdbp_header *part;
  
        if (!smu)
                return NULL;
        } else
                mutex_lock(&smu_part_access);
  
 -      part = (struct smu_sdbp_header *)get_property(smu->of_node,
 -                                                    pname, size);
 +      part = get_property(smu->of_node, pname, size);
        if (part == NULL) {
                DPRINTK("trying to extract from SMU ...\n");
                part = smu_create_sdb_partition(id);
        return part;
  }
  
 -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size)
 +const struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size)
  {
        return __smu_get_sdb_partition(id, size, 0);
  }
@@@ -1070,7 -1094,7 +1093,7 @@@ static ssize_t smu_write(struct file *f
                pp->mode = smu_file_events;
                return 0;
        } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) {
 -              struct smu_sdbp_header *part;
 +              const struct smu_sdbp_header *part;
                part = __smu_get_sdb_partition(hdr.cmd, NULL, 1);
                if (part == NULL)
                        return -EINVAL;
@@@ -16,7 -16,6 +16,6 @@@
   *    a sleep or a freq. switch
   *  - Move sleep code out of here to pmac_pm, merge into new
   *    common PM infrastructure
-  *  - Move backlight code out as well
   *  - Save/Restore PCI space properly
   *
   */
@@@ -60,9 -59,7 +59,7 @@@
  #include <asm/mmu_context.h>
  #include <asm/cputable.h>
  #include <asm/time.h>
- #ifdef CONFIG_PMAC_BACKLIGHT
  #include <asm/backlight.h>
- #endif
  
  #include "via-pmu-event.h"
  
@@@ -177,10 -174,6 +174,6 @@@ static int query_batt_timer = BATTERY_P
  static struct adb_request batt_req;
  static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
  
- #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
- extern int disable_kernel_backlight;
- #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
  int __fake_sleep;
  int asleep;
  BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
@@@ -287,7 -280,7 +280,7 @@@ static char *pbook_type[] = 
  int __init find_via_pmu(void)
  {
        u64 taddr;
 -      u32 *reg;
 +      const u32 *reg;
  
        if (via != 0)
                return 1;
        if (vias == NULL)
                return 0;
  
 -      reg = (u32 *)get_property(vias, "reg", NULL);
 +      reg = get_property(vias, "reg", NULL);
        if (reg == NULL) {
                printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
                goto fail;
                
                gpiop = of_find_node_by_name(NULL, "gpio");
                if (gpiop) {
 -                      reg = (u32 *)get_property(gpiop, "reg", NULL);
 +                      reg = get_property(gpiop, "reg", NULL);
                        if (reg)
                                gaddr = of_translate_address(gpiop, reg);
                        if (gaddr != OF_BAD_ADDR)
@@@ -466,7 -459,7 +459,7 @@@ static int __init via_pmu_dev_init(void
  
  #ifdef CONFIG_PMAC_BACKLIGHT
        /* Initialize backlight */
-       pmu_backlight_init(vias);
+       pmu_backlight_init();
  #endif
  
  #ifdef CONFIG_PPC32
                pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
        } else {
                struct device_node* prim = find_devices("power-mgt");
 -              u32 *prim_info = NULL;
 +              const u32 *prim_info = NULL;
                if (prim)
 -                      prim_info = (u32 *)get_property(prim, "prim-info", NULL);
 +                      prim_info = get_property(prim, "prim-info", NULL);
                if (prim_info) {
                        /* Other stuffs here yet unknown */
                        pmu_battery_count = (prim_info[6] >> 16) & 0xff;
@@@ -1403,11 -1396,8 +1396,8 @@@ next
        else if ((1 << pirq) & PMU_INT_SNDBRT) {
  #ifdef CONFIG_PMAC_BACKLIGHT
                if (len == 3)
- #ifdef CONFIG_INPUT_ADBHID
-                       if (!disable_kernel_backlight)
- #endif /* CONFIG_INPUT_ADBHID */
-                               pmac_backlight_set_legacy_brightness(data[1] >> 4);
- #endif /* CONFIG_PMAC_BACKLIGHT */
+                       pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4);
+ #endif
        }
        /* Tick interrupt */
        else if ((1 << pirq) & PMU_INT_TICK) {
@@@ -2414,7 -2404,7 +2404,7 @@@ struct pmu_private 
        spinlock_t lock;
  #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
        int     backlight_locker;
- #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */   
+ #endif
  };
  
  static LIST_HEAD(all_pmu_pvt);
@@@ -2464,7 -2454,7 +2454,7 @@@ pmu_open(struct inode *inode, struct fi
        spin_lock_irqsave(&all_pvt_lock, flags);
  #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
        pp->backlight_locker = 0;
- #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */   
+ #endif
        list_add(&pp->list, &all_pmu_pvt);
        spin_unlock_irqrestore(&all_pvt_lock, flags);
        file->private_data = pp;
@@@ -2559,13 -2549,12 +2549,12 @@@ pmu_release(struct inode *inode, struc
                spin_lock_irqsave(&all_pvt_lock, flags);
                list_del(&pp->list);
                spin_unlock_irqrestore(&all_pvt_lock, flags);
  #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
-               if (pp->backlight_locker) {
-                       spin_lock_irqsave(&pmu_lock, flags);
-                       disable_kernel_backlight--;
-                       spin_unlock_irqrestore(&pmu_lock, flags);
-               }
- #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+               if (pp->backlight_locker)
+                       pmac_backlight_enable();
+ #endif
                kfree(pp);
        }
        unlock_kernel();
@@@ -2642,18 -2631,18 +2631,18 @@@ pmu_ioctl(struct inode * inode, struct 
  #ifdef CONFIG_INPUT_ADBHID
        case PMU_IOC_GRAB_BACKLIGHT: {
                struct pmu_private *pp = filp->private_data;
  
                if (pp->backlight_locker)
                        return 0;
                pp->backlight_locker = 1;
-               spin_lock_irqsave(&pmu_lock, flags);
-               disable_kernel_backlight++;
-               spin_unlock_irqrestore(&pmu_lock, flags);
+               pmac_backlight_disable();
                return 0;
        }
  #endif /* CONFIG_INPUT_ADBHID */
  #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
        case PMU_IOC_GET_MODEL:
                return put_user(pmu_kind, argp);
        case PMU_IOC_HAS_ADB:
diff --combined drivers/net/spider_net.c
@@@ -84,7 -84,7 +84,7 @@@ MODULE_DEVICE_TABLE(pci, spider_net_pci
   *
   * returns the content of the specified SMMIO register.
   */
- static u32
+ static inline u32
  spider_net_read_reg(struct spider_net_card *card, u32 reg)
  {
        u32 value;
   * @reg: register to write to
   * @value: value to write into the specified SMMIO register
   */
- static void
+ static inline void
  spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
  {
        value = cpu_to_le32(value);
@@@ -259,39 -259,10 +259,10 @@@ spider_net_get_mac_address(struct net_d
   *
   * returns the status as in the dmac_cmd_status field of the descriptor
   */
- static enum spider_net_descr_status
+ static inline int
  spider_net_get_descr_status(struct spider_net_descr *descr)
  {
-       u32 cmd_status;
-       cmd_status = descr->dmac_cmd_status;
-       cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
-       /* no need to mask out any bits, as cmd_status is 32 bits wide only
-        * (and unsigned) */
-       return cmd_status;
- }
- /**
-  * spider_net_set_descr_status -- sets the status of a descriptor
-  * @descr: descriptor to change
-  * @status: status to set in the descriptor
-  *
-  * changes the status to the specified value. Doesn't change other bits
-  * in the status
-  */
- static void
- spider_net_set_descr_status(struct spider_net_descr *descr,
-                           enum spider_net_descr_status status)
- {
-       u32 cmd_status;
-       /* read the status */
-       cmd_status = descr->dmac_cmd_status;
-       /* clean the upper 4 bits */
-       cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
-       /* add the status to it */
-       cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
-       /* and write it back */
-       descr->dmac_cmd_status = cmd_status;
+       return descr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
  }
  
  /**
@@@ -328,24 -299,23 +299,23 @@@ spider_net_free_chain(struct spider_net
  static int
  spider_net_init_chain(struct spider_net_card *card,
                       struct spider_net_descr_chain *chain,
-                      struct spider_net_descr *start_descr, int no)
+                      struct spider_net_descr *start_descr,
+                      int direction, int no)
  {
        int i;
        struct spider_net_descr *descr;
        dma_addr_t buf;
  
-       atomic_set(&card->rx_chain_refill,0);
        descr = start_descr;
        memset(descr, 0, sizeof(*descr) * no);
  
        /* set up the hardware pointers in each descriptor */
        for (i=0; i<no; i++, descr++) {
-               spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+               descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
  
                buf = pci_map_single(card->pdev, descr,
                                     SPIDER_NET_DESCR_SIZE,
-                                    PCI_DMA_BIDIRECTIONAL);
+                                    direction);
  
                if (buf == DMA_ERROR_CODE)
                        goto iommu_error;
        start_descr->prev = descr-1;
  
        descr = start_descr;
-       for (i=0; i < no; i++, descr++) {
-               descr->next_descr_addr = descr->next->bus_addr;
-       }
+       if (direction == PCI_DMA_FROMDEVICE)
+               for (i=0; i < no; i++, descr++)
+                       descr->next_descr_addr = descr->next->bus_addr;
  
+       spin_lock_init(&chain->lock);
        chain->head = start_descr;
        chain->tail = start_descr;
  
@@@ -375,7 -346,7 +346,7 @@@ iommu_error
                if (descr->bus_addr)
                        pci_unmap_single(card->pdev, descr->bus_addr,
                                         SPIDER_NET_DESCR_SIZE,
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        direction);
        return -ENOMEM;
  }
  
@@@ -396,7 -367,7 +367,7 @@@ spider_net_free_rx_chain_contents(struc
                        dev_kfree_skb(descr->skb);
                        pci_unmap_single(card->pdev, descr->buf_addr,
                                         SPIDER_NET_MAX_FRAME,
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        PCI_DMA_FROMDEVICE);
                }
                descr = descr->next;
        }
@@@ -446,15 -417,16 +417,16 @@@ spider_net_prepare_rx_descr(struct spid
                skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
        /* io-mmu-map the skb */
        buf = pci_map_single(card->pdev, descr->skb->data,
-                            SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+                       SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
        descr->buf_addr = buf;
        if (buf == DMA_ERROR_CODE) {
                dev_kfree_skb_any(descr->skb);
                if (netif_msg_rx_err(card) && net_ratelimit())
                        pr_err("Could not iommu-map rx buffer\n");
-               spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+               descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
        } else {
-               descr->dmac_cmd_status = SPIDER_NET_DMAC_RX_CARDOWNED;
+               descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
+                                        SPIDER_NET_DMAC_NOINTR_COMPLETE;
        }
  
        return error;
   * chip by writing to the appropriate register. DMA is enabled in
   * spider_net_enable_rxdmac.
   */
- static void
+ static inline void
  spider_net_enable_rxchtails(struct spider_net_card *card)
  {
        /* assume chain is aligned correctly */
   * spider_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
   * in the GDADMACCNTR register
   */
- static void
+ static inline void
  spider_net_enable_rxdmac(struct spider_net_card *card)
  {
        wmb();
  static void
  spider_net_refill_rx_chain(struct spider_net_card *card)
  {
-       struct spider_net_descr_chain *chain;
-       chain = &card->rx_chain;
+       struct spider_net_descr_chain *chain = &card->rx_chain;
+       unsigned long flags;
  
        /* one context doing the refill (and a second context seeing that
         * and omitting it) is ok. If called by NAPI, we'll be called again
         * as spider_net_decode_one_descr is called several times. If some
         * interrupt calls us, the NAPI is about to clean up anyway. */
-       if (atomic_inc_return(&card->rx_chain_refill) == 1)
-               while (spider_net_get_descr_status(chain->head) ==
-                      SPIDER_NET_DESCR_NOT_IN_USE) {
-                       if (spider_net_prepare_rx_descr(card, chain->head))
-                               break;
-                       chain->head = chain->head->next;
-               }
+       if (!spin_trylock_irqsave(&chain->lock, flags))
+               return;
+       while (spider_net_get_descr_status(chain->head) ==
+                       SPIDER_NET_DESCR_NOT_IN_USE) {
+               if (spider_net_prepare_rx_descr(card, chain->head))
+                       break;
+               chain->head = chain->head->next;
+       }
  
-       atomic_dec(&card->rx_chain_refill);
+       spin_unlock_irqrestore(&chain->lock, flags);
  }
  
  /**
@@@ -554,111 -527,6 +527,6 @@@ error
  }
  
  /**
-  * spider_net_release_tx_descr - processes a used tx descriptor
-  * @card: card structure
-  * @descr: descriptor to release
-  *
-  * releases a used tx descriptor (unmapping, freeing of skb)
-  */
- static void
- spider_net_release_tx_descr(struct spider_net_card *card,
-                           struct spider_net_descr *descr)
- {
-       struct sk_buff *skb;
-       /* unmap the skb */
-       skb = descr->skb;
-       pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
-                        PCI_DMA_BIDIRECTIONAL);
-       dev_kfree_skb_any(skb);
-       /* set status to not used */
-       spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
- }
- /**
-  * spider_net_release_tx_chain - processes sent tx descriptors
-  * @card: adapter structure
-  * @brutal: if set, don't care about whether descriptor seems to be in use
-  *
-  * returns 0 if the tx ring is empty, otherwise 1.
-  *
-  * spider_net_release_tx_chain releases the tx descriptors that spider has
-  * finished with (if non-brutal) or simply release tx descriptors (if brutal).
-  * If some other context is calling this function, we return 1 so that we're
-  * scheduled again (if we were scheduled) and will not loose initiative.
-  */
- static int
- spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
- {
-       struct spider_net_descr_chain *tx_chain = &card->tx_chain;
-       enum spider_net_descr_status status;
-       if (atomic_inc_return(&card->tx_chain_release) != 1) {
-               atomic_dec(&card->tx_chain_release);
-               return 1;
-       }
-       for (;;) {
-               status = spider_net_get_descr_status(tx_chain->tail);
-               switch (status) {
-               case SPIDER_NET_DESCR_CARDOWNED:
-                       if (!brutal)
-                               goto out;
-                       /* fallthrough, if we release the descriptors
-                        * brutally (then we don't care about
-                        * SPIDER_NET_DESCR_CARDOWNED) */
-               case SPIDER_NET_DESCR_RESPONSE_ERROR:
-               case SPIDER_NET_DESCR_PROTECTION_ERROR:
-               case SPIDER_NET_DESCR_FORCE_END:
-                       if (netif_msg_tx_err(card))
-                               pr_err("%s: forcing end of tx descriptor "
-                                      "with status x%02x\n",
-                                      card->netdev->name, status);
-                       card->netdev_stats.tx_dropped++;
-                       break;
-               case SPIDER_NET_DESCR_COMPLETE:
-                       card->netdev_stats.tx_packets++;
-                       card->netdev_stats.tx_bytes +=
-                               tx_chain->tail->skb->len;
-                       break;
-               default: /* any other value (== SPIDER_NET_DESCR_NOT_IN_USE) */
-                       goto out;
-               }
-               spider_net_release_tx_descr(card, tx_chain->tail);
-               tx_chain->tail = tx_chain->tail->next;
-       }
- out:
-       atomic_dec(&card->tx_chain_release);
-       netif_wake_queue(card->netdev);
-       if (status == SPIDER_NET_DESCR_CARDOWNED)
-               return 1;
-       return 0;
- }
- /**
-  * spider_net_cleanup_tx_ring - cleans up the TX ring
-  * @card: card structure
-  *
-  * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
-  * interrupts to cleanup our TX ring) and returns sent packets to the stack
-  * by freeing them
-  */
- static void
- spider_net_cleanup_tx_ring(struct spider_net_card *card)
- {
-       if ( (spider_net_release_tx_chain(card, 0)) &&
-             (card->netdev->flags & IFF_UP) ) {
-               mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
-       }
- }
- /**
   * spider_net_get_multicast_hash - generates hash for multicast filter table
   * @addr: multicast address
   *
@@@ -761,97 -629,6 +629,6 @@@ spider_net_disable_rxdmac(struct spider
  }
  
  /**
-  * spider_net_stop - called upon ifconfig down
-  * @netdev: interface device structure
-  *
-  * always returns 0
-  */
- int
- spider_net_stop(struct net_device *netdev)
- {
-       struct spider_net_card *card = netdev_priv(netdev);
-       tasklet_kill(&card->rxram_full_tl);
-       netif_poll_disable(netdev);
-       netif_carrier_off(netdev);
-       netif_stop_queue(netdev);
-       del_timer_sync(&card->tx_timer);
-       /* disable/mask all interrupts */
-       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
-       spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
-       spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
-       /* free_irq(netdev->irq, netdev);*/
-       free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
-       spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
-                            SPIDER_NET_DMA_TX_FEND_VALUE);
-       /* turn off DMA, force end */
-       spider_net_disable_rxdmac(card);
-       /* release chains */
-       spider_net_release_tx_chain(card, 1);
-       spider_net_free_chain(card, &card->tx_chain);
-       spider_net_free_chain(card, &card->rx_chain);
-       return 0;
- }
- /**
-  * spider_net_get_next_tx_descr - returns the next available tx descriptor
-  * @card: device structure to get descriptor from
-  *
-  * returns the address of the next descriptor, or NULL if not available.
-  */
- static struct spider_net_descr *
- spider_net_get_next_tx_descr(struct spider_net_card *card)
- {
-       /* check, if head points to not-in-use descr */
-       if ( spider_net_get_descr_status(card->tx_chain.head) ==
-            SPIDER_NET_DESCR_NOT_IN_USE ) {
-               return card->tx_chain.head;
-       } else {
-               return NULL;
-       }
- }
- /**
-  * spider_net_set_txdescr_cmdstat - sets the tx descriptor command field
-  * @descr: descriptor structure to fill out
-  * @skb: packet to consider
-  *
-  * fills out the command and status field of the descriptor structure,
-  * depending on hardware checksum settings.
-  */
- static void
- spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
-                              struct sk_buff *skb)
- {
-       /* make sure the other fields in the descriptor are written */
-       wmb();
-       if (skb->ip_summed != CHECKSUM_HW) {
-               descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
-               return;
-       }
-       /* is packet ip?
-        * if yes: tcp? udp? */
-       if (skb->protocol == htons(ETH_P_IP)) {
-               if (skb->nh.iph->protocol == IPPROTO_TCP)
-                       descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
-               else if (skb->nh.iph->protocol == IPPROTO_UDP)
-                       descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
-               else /* the stack should checksum non-tcp and non-udp
-                       packets on his own: NETIF_F_IP_CSUM */
-                       descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
-       }
- }
- /**
   * spider_net_prepare_tx_descr - fill tx descriptor with skb data
   * @card: card structure
   * @descr: descriptor structure to fill out
   */
  static int
  spider_net_prepare_tx_descr(struct spider_net_card *card,
-                           struct spider_net_descr *descr,
                            struct sk_buff *skb)
  {
+       struct spider_net_descr *descr = card->tx_chain.head;
        dma_addr_t buf;
  
-       buf = pci_map_single(card->pdev, skb->data,
-                            skb->len, PCI_DMA_BIDIRECTIONAL);
+       buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
        if (buf == DMA_ERROR_CODE) {
                if (netif_msg_tx_err(card) && net_ratelimit())
                        pr_err("could not iommu-map packet (%p, %i). "
  
        descr->buf_addr = buf;
        descr->buf_size = skb->len;
+       descr->next_descr_addr = 0;
        descr->skb = skb;
        descr->data_status = 0;
  
-       spider_net_set_txdescr_cmdstat(descr,skb);
+       descr->dmac_cmd_status =
+                       SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+       if (skb->protocol == htons(ETH_P_IP))
+               switch (skb->nh.iph->protocol) {
+               case IPPROTO_TCP:
+                       descr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
+                       break;
+               case IPPROTO_UDP:
+                       descr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
+                       break;
+               }
+       descr->prev->next_descr_addr = descr->bus_addr;
+       return 0;
+ }
+ /**
+  * spider_net_release_tx_descr - processes a used tx descriptor
+  * @card: card structure
+  * @descr: descriptor to release
+  *
+  * releases a used tx descriptor (unmapping, freeing of skb)
+  */
+ static inline void
+ spider_net_release_tx_descr(struct spider_net_card *card)
+ {
+       struct spider_net_descr *descr = card->tx_chain.tail;
+       struct sk_buff *skb;
+       card->tx_chain.tail = card->tx_chain.tail->next;
+       descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+       /* unmap the skb */
+       skb = descr->skb;
+       pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
+                       PCI_DMA_TODEVICE);
+       dev_kfree_skb_any(skb);
+ }
+ /**
+  * spider_net_release_tx_chain - processes sent tx descriptors
+  * @card: adapter structure
+  * @brutal: if set, don't care about whether descriptor seems to be in use
+  *
+  * returns 0 if the tx ring is empty, otherwise 1.
+  *
+  * spider_net_release_tx_chain releases the tx descriptors that spider has
+  * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+  * If some other context is calling this function, we return 1 so that we're
+  * scheduled again (if we were scheduled) and will not loose initiative.
+  */
+ static int
+ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
+ {
+       struct spider_net_descr_chain *chain = &card->tx_chain;
+       int status;
+       spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
+       while (chain->tail != chain->head) {
+               status = spider_net_get_descr_status(chain->tail);
+               switch (status) {
+               case SPIDER_NET_DESCR_COMPLETE:
+                       card->netdev_stats.tx_packets++;
+                       card->netdev_stats.tx_bytes += chain->tail->skb->len;
+                       break;
+               case SPIDER_NET_DESCR_CARDOWNED:
+                       if (!brutal)
+                               return 1;
+                       /* fallthrough, if we release the descriptors
+                        * brutally (then we don't care about
+                        * SPIDER_NET_DESCR_CARDOWNED) */
+               case SPIDER_NET_DESCR_RESPONSE_ERROR:
+               case SPIDER_NET_DESCR_PROTECTION_ERROR:
+               case SPIDER_NET_DESCR_FORCE_END:
+                       if (netif_msg_tx_err(card))
+                               pr_err("%s: forcing end of tx descriptor "
+                                      "with status x%02x\n",
+                                      card->netdev->name, status);
+                       card->netdev_stats.tx_errors++;
+                       break;
+               default:
+                       card->netdev_stats.tx_dropped++;
+                       return 1;
+               }
+               spider_net_release_tx_descr(card);
+       }
  
        return 0;
  }
   * spider_net_kick_tx_dma writes the current tx chain head as start address
   * of the tx descriptor chain and enables the transmission DMA engine
   */
- static void
- spider_net_kick_tx_dma(struct spider_net_card *card,
-                      struct spider_net_descr *descr)
+ static inline void
+ spider_net_kick_tx_dma(struct spider_net_card *card)
  {
-       /* this is the only descriptor in the output chain.
-        * Enable TX DMA */
+       struct spider_net_descr *descr;
  
-       spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
-                            descr->bus_addr);
+       if (spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR) &
+                       SPIDER_NET_TX_DMA_EN)
+               goto out;
  
-       spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
-                            SPIDER_NET_DMA_TX_VALUE);
+       descr = card->tx_chain.tail;
+       for (;;) {
+               if (spider_net_get_descr_status(descr) ==
+                               SPIDER_NET_DESCR_CARDOWNED) {
+                       spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+                                       descr->bus_addr);
+                       spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+                                       SPIDER_NET_DMA_TX_VALUE);
+                       break;
+               }
+               if (descr == card->tx_chain.head)
+                       break;
+               descr = descr->next;
+       }
+ out:
+       mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
  }
  
  /**
   * @skb: packet to send out
   * @netdev: interface device structure
   *
-  * returns 0 on success, <0 on failure
+  * returns 0 on success, !0 on failure
   */
  static int
  spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
  {
        struct spider_net_card *card = netdev_priv(netdev);
-       struct spider_net_descr *descr;
+       struct spider_net_descr_chain *chain = &card->tx_chain;
+       struct spider_net_descr *descr = chain->head;
+       unsigned long flags;
        int result;
  
+       spin_lock_irqsave(&chain->lock, flags);
        spider_net_release_tx_chain(card, 0);
  
-       descr = spider_net_get_next_tx_descr(card);
+       if (chain->head->next == chain->tail->prev) {
+               card->netdev_stats.tx_dropped++;
+               result = NETDEV_TX_LOCKED;
+               goto out;
+       }
+       if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) {
+               result = NETDEV_TX_LOCKED;
+               goto out;
+       }
  
-       if (!descr)
-               goto error;
+       if (spider_net_prepare_tx_descr(card, skb) != 0) {
+               card->netdev_stats.tx_dropped++;
+               result = NETDEV_TX_BUSY;
+               goto out;
+       }
  
-       result = spider_net_prepare_tx_descr(card, descr, skb);
-       if (result)
-               goto error;
+       result = NETDEV_TX_OK;
  
+       spider_net_kick_tx_dma(card);
        card->tx_chain.head = card->tx_chain.head->next;
  
-       if (spider_net_get_descr_status(descr->prev) !=
-           SPIDER_NET_DESCR_CARDOWNED) {
-               /* make sure the current descriptor is in memory. Then
-                * kicking it on again makes sense, if the previous is not
-                * card-owned anymore. Check the previous descriptor twice
-                * to omit an mb() in heavy traffic cases */
-               mb();
-               if (spider_net_get_descr_status(descr->prev) !=
-                   SPIDER_NET_DESCR_CARDOWNED)
-                       spider_net_kick_tx_dma(card, descr);
-       }
+ out:
+       spin_unlock_irqrestore(&chain->lock, flags);
+       netif_wake_queue(netdev);
+       return result;
+ }
  
-       mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+ /**
+  * spider_net_cleanup_tx_ring - cleans up the TX ring
+  * @card: card structure
+  *
+  * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+  * interrupts to cleanup our TX ring) and returns sent packets to the stack
+  * by freeing them
+  */
+ static void
+ spider_net_cleanup_tx_ring(struct spider_net_card *card)
+ {
+       unsigned long flags;
  
-       return NETDEV_TX_OK;
+       spin_lock_irqsave(&card->tx_chain.lock, flags);
  
- error:
-       card->netdev_stats.tx_dropped++;
-       return NETDEV_TX_BUSY;
+       if ((spider_net_release_tx_chain(card, 0) != 0) &&
+           (card->netdev->flags & IFF_UP))
+               spider_net_kick_tx_dma(card);
+       spin_unlock_irqrestore(&card->tx_chain.lock, flags);
  }
  
  /**
@@@ -1002,7 -905,7 +905,7 @@@ spider_net_pass_skb_up(struct spider_ne
  
        /* unmap descriptor */
        pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
-                        PCI_DMA_BIDIRECTIONAL);
+                       PCI_DMA_FROMDEVICE);
  
        /* the cases we'll throw away the packet immediately */
        if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
  static int
  spider_net_decode_one_descr(struct spider_net_card *card, int napi)
  {
-       enum spider_net_descr_status status;
-       struct spider_net_descr *descr;
-       struct spider_net_descr_chain *chain;
+       struct spider_net_descr_chain *chain = &card->rx_chain;
+       struct spider_net_descr *descr = chain->tail;
+       int status;
        int result;
  
-       chain = &card->rx_chain;
-       descr = chain->tail;
        status = spider_net_get_descr_status(descr);
  
        if (status == SPIDER_NET_DESCR_CARDOWNED) {
                               card->netdev->name, status);
                card->netdev_stats.rx_dropped++;
                pci_unmap_single(card->pdev, descr->buf_addr,
-                                SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+                               SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
                dev_kfree_skb_irq(descr->skb);
                goto refill;
        }
        /* ok, we've got a packet in descr */
        result = spider_net_pass_skb_up(descr, card, napi);
  refill:
-       spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+       descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
        /* change the descriptor state: */
        if (!napi)
                spider_net_refill_rx_chain(card);
@@@ -1291,21 -1191,6 +1191,6 @@@ spider_net_set_mac(struct net_device *n
  }
  
  /**
-  * spider_net_enable_txdmac - enables a TX DMA controller
-  * @card: card structure
-  *
-  * spider_net_enable_txdmac enables the TX DMA controller by setting the
-  * descriptor chain tail address
-  */
- static void
- spider_net_enable_txdmac(struct spider_net_card *card)
- {
-       /* assume chain is aligned correctly */
-       spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
-                            card->tx_chain.tail->bus_addr);
- }
- /**
   * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
   * @card: card structure
   *
@@@ -1653,7 -1538,6 +1538,6 @@@ spider_net_enable_card(struct spider_ne
                { SPIDER_NET_GMRWOLCTRL, 0 },
                { SPIDER_NET_GTESTMD, 0x10000000 },
                { SPIDER_NET_GTTQMSK, 0x00400040 },
-               { SPIDER_NET_GTESTMD, 0 },
  
                { SPIDER_NET_GMACINTEN, 0 },
  
  
        spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE);
  
-       /* set chain tail adress for TX chain */
-       spider_net_enable_txdmac(card);
        spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
                             SPIDER_NET_LENLMT_VALUE);
        spider_net_write_reg(card, SPIDER_NET_GMACMODE,
                             SPIDER_NET_INT1_MASK_VALUE);
        spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
                             SPIDER_NET_INT2_MASK_VALUE);
+       spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+                            SPIDER_NET_GDTDCEIDIS);
  }
  
  /**
@@@ -1728,10 -1612,12 +1612,12 @@@ spider_net_open(struct net_device *netd
  
        result = -ENOMEM;
        if (spider_net_init_chain(card, &card->tx_chain,
-                         card->descr, tx_descriptors))
+                       card->descr,
+                       PCI_DMA_TODEVICE, tx_descriptors))
                goto alloc_tx_failed;
        if (spider_net_init_chain(card, &card->rx_chain,
-                         card->descr + tx_descriptors, rx_descriptors))
+                       card->descr + tx_descriptors,
+                       PCI_DMA_FROMDEVICE, rx_descriptors))
                goto alloc_rx_failed;
  
        /* allocate rx skbs */
@@@ -1812,10 -1698,10 +1698,10 @@@ spider_net_setup_phy(struct spider_net_
   */
  static int
  spider_net_download_firmware(struct spider_net_card *card,
 -                           u8 *firmware_ptr)
 +                           const void *firmware_ptr)
  {
        int sequencer, i;
 -      u32 *fw_ptr = (u32 *)firmware_ptr;
 +      const u32 *fw_ptr = firmware_ptr;
  
        /* stop sequencers */
        spider_net_write_reg(card, SPIDER_NET_GSINIT,
@@@ -1872,7 -1758,7 +1758,7 @@@ spider_net_init_firmware(struct spider_
  {
        struct firmware *firmware = NULL;
        struct device_node *dn;
 -      u8 *fw_prop = NULL;
 +      const u8 *fw_prop = NULL;
        int err = -ENOENT;
        int fw_size;
  
@@@ -1898,7 -1784,7 +1784,7 @@@ try_host_fw
        if (!dn)
                goto out_err;
  
 -      fw_prop = (u8 *)get_property(dn, "firmware", &fw_size);
 +      fw_prop = get_property(dn, "firmware", &fw_size);
        if (!fw_prop)
                goto out_err;
  
@@@ -1938,7 -1824,7 +1824,7 @@@ spider_net_workaround_rxramfull(struct 
        /* empty sequencer data */
        for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
             sequencer++) {
-               spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+               spider_net_write_reg(card, SPIDER_NET_GSnPRGADR +
                                     sequencer * 8, 0x0);
                for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
                        spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
  }
  
  /**
+  * spider_net_stop - called upon ifconfig down
+  * @netdev: interface device structure
+  *
+  * always returns 0
+  */
+ int
+ spider_net_stop(struct net_device *netdev)
+ {
+       struct spider_net_card *card = netdev_priv(netdev);
+       tasklet_kill(&card->rxram_full_tl);
+       netif_poll_disable(netdev);
+       netif_carrier_off(netdev);
+       netif_stop_queue(netdev);
+       del_timer_sync(&card->tx_timer);
+       /* disable/mask all interrupts */
+       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+       spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+       spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+       /* free_irq(netdev->irq, netdev);*/
+       free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+       spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+                            SPIDER_NET_DMA_TX_FEND_VALUE);
+       /* turn off DMA, force end */
+       spider_net_disable_rxdmac(card);
+       /* release chains */
+       if (spin_trylock(&card->tx_chain.lock)) {
+               spider_net_release_tx_chain(card, 1);
+               spin_unlock(&card->tx_chain.lock);
+       }
+       spider_net_free_chain(card, &card->tx_chain);
+       spider_net_free_chain(card, &card->rx_chain);
+       return 0;
+ }
+ /**
   * spider_net_tx_timeout_task - task scheduled by the watchdog timeout
   * function (to be called not under interrupt status)
   * @data: data, is interface device structure
@@@ -1982,7 -1911,7 +1911,7 @@@ spider_net_tx_timeout_task(void *data
                goto out;
  
        spider_net_open(netdev);
-       spider_net_kick_tx_dma(card, card->tx_chain.head);
+       spider_net_kick_tx_dma(card);
        netif_device_attach(netdev);
  
  out:
@@@ -2058,14 -1987,13 +1987,13 @@@ spider_net_setup_netdev(struct spider_n
        struct net_device *netdev = card->netdev;
        struct device_node *dn;
        struct sockaddr addr;
 -      u8 *mac;
 +      const u8 *mac;
  
        SET_MODULE_OWNER(netdev);
        SET_NETDEV_DEV(netdev, &card->pdev->dev);
  
        pci_set_drvdata(card->pdev, netdev);
  
-       atomic_set(&card->tx_chain_release,0);
        card->rxram_full_tl.data = (unsigned long) card;
        card->rxram_full_tl.func =
                (void (*)(unsigned long)) spider_net_handle_rxram_full;
  
        spider_net_setup_netdev_ops(netdev);
  
-       netdev->features = NETIF_F_HW_CSUM;
+       netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
        /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
         *              NETIF_F_HW_VLAN_FILTER */
  
        if (!dn)
                return -EIO;
  
 -      mac = (u8 *)get_property(dn, "local-mac-address", NULL);
 +      mac = get_property(dn, "local-mac-address", NULL);
        if (!mac)
                return -EIO;
        memcpy(addr.sa_data, mac, ETH_ALEN);
@@@ -156,8 -156,8 +156,8 @@@ static void gather_partition_info(void
  {
        struct device_node *rootdn;
  
 -      char *ppartition_name;
 -      unsigned int *p_number_ptr;
 +      const char *ppartition_name;
 +      const unsigned int *p_number_ptr;
  
        /* Retrieve information about this partition */
        rootdn = find_path_device("/");
                return;
        }
  
 -      ppartition_name =
 -              get_property(rootdn, "ibm,partition-name", NULL);
 +      ppartition_name = get_property(rootdn, "ibm,partition-name", NULL);
        if (ppartition_name)
                strncpy(partition_name, ppartition_name,
                                sizeof(partition_name));
 -      p_number_ptr =
 -              (unsigned int *)get_property(rootdn, "ibm,partition-no",
 -                                           NULL);
 +      p_number_ptr = get_property(rootdn, "ibm,partition-no", NULL);
        if (p_number_ptr)
                partition_number = *p_number_ptr;
  }
@@@ -235,6 -238,7 +235,7 @@@ int ibmvscsi_init_crq_queue(struct crq_
        if (rc == 2) {
                /* Adapter is good, but other end is not ready */
                printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+               retrc = 0;
        } else if (rc != 0) {
                printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
                goto reg_crq_failed;
diff --combined drivers/scsi/mac53c94.c
@@@ -378,7 -378,7 +378,7 @@@ static void set_dma_cmds(struct fsc_sta
                int nseg;
  
                total = 0;
-               scl = (struct scatterlist *) cmd->buffer;
+               scl = (struct scatterlist *) cmd->request_buffer;
                nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
                                cmd->sc_data_direction);
                for (i = 0; i < nseg; ++i) {
@@@ -431,7 -431,7 +431,7 @@@ static int mac53c94_probe(struct macio_
        struct fsc_state *state;
        struct Scsi_Host *host;
        void *dma_cmd_space;
 -      unsigned char *clkprop;
 +      const unsigned char *clkprop;
        int proplen, rc = -ENODEV;
  
        if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
diff --combined drivers/scsi/mesh.c
@@@ -1268,7 -1268,7 +1268,7 @@@ static void set_dma_cmds(struct mesh_st
                if (cmd->use_sg > 0) {
                        int nseg;
                        total = 0;
-                       scl = (struct scatterlist *) cmd->buffer;
+                       scl = (struct scatterlist *) cmd->request_buffer;
                        off = ms->data_ptr;
                        nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
                                          cmd->sc_data_direction);
@@@ -1850,8 -1850,7 +1850,8 @@@ static int mesh_probe(struct macio_dev 
  {
        struct device_node *mesh = macio_get_of_node(mdev);
        struct pci_dev* pdev = macio_get_pci_dev(mdev);
 -      int tgt, *cfp, minper;
 +      int tgt, minper;
 +      const int *cfp;
        struct mesh_state *ms;
        struct Scsi_Host *mesh_host;
        void *dma_cmd_space;
                ms->tgts[tgt].current_req = NULL;
                }
  
 -      if ((cfp = (int *) get_property(mesh, "clock-frequency", NULL)))
 +      if ((cfp = get_property(mesh, "clock-frequency", NULL)))
                        ms->clk_freq = *cfp;
        else {
                        printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n");
diff --combined drivers/video/S3triofb.c
@@@ -28,7 -28,6 +28,6 @@@
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/mm.h>
- #include <linux/tty.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
  #include <linux/delay.h>
@@@ -350,30 -349,30 +349,30 @@@ static void __init s3triofb_of_init(str
      s3trio_name[sizeof(s3trio_name)-1] = '\0';
      strcpy(fb_fix.id, s3trio_name);
  
 -    if((pp = (int *)get_property(dp, "vendor-id", &len)) != NULL
 +    if((pp = get_property(dp, "vendor-id", &len)) != NULL
        && *pp!=PCI_VENDOR_ID_S3) {
        printk("%s: can't find S3 Trio board\n", dp->full_name);
        return;
      }
  
 -    if((pp = (int *)get_property(dp, "device-id", &len)) != NULL
 +    if((pp = get_property(dp, "device-id", &len)) != NULL
        && *pp!=PCI_DEVICE_ID_S3_TRIO) {
        printk("%s: can't find S3 Trio board\n", dp->full_name);
        return;
      }
  
 -    if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
 +    if ((pp = get_property(dp, "depth", &len)) != NULL
        && len == sizeof(int) && *pp != 8) {
        printk("%s: can't use depth = %d\n", dp->full_name, *pp);
        return;
      }
 -    if ((pp = (int *)get_property(dp, "width", &len)) != NULL
 +    if ((pp = get_property(dp, "width", &len)) != NULL
        && len == sizeof(int))
        fb_var.xres = fb_var.xres_virtual = *pp;
 -    if ((pp = (int *)get_property(dp, "height", &len)) != NULL
 +    if ((pp = get_property(dp, "height", &len)) != NULL
        && len == sizeof(int))
        fb_var.yres = fb_var.yres_virtual = *pp;
 -    if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
 +    if ((pp = get_property(dp, "linebytes", &len)) != NULL
        && len == sizeof(int))
        fb_fix.line_length = *pp;
      else
@@@ -58,7 -58,6 +58,6 @@@
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/mm.h>
- #include <linux/tty.h>
  #include <linux/slab.h>
  #include <linux/delay.h>
  #include <linux/time.h>
@@@ -267,6 -266,8 +266,8 @@@ static int force_measure_pll = 0
  #ifdef CONFIG_MTRR
  static int nomtrr = 0;
  #endif
+ static int force_sleep;
+ static int ignore_devlist;
  
  /*
   * prototypes
@@@ -412,11 -413,11 +413,11 @@@ static int  __devinit radeon_find_mem_v
  static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
  {
        struct device_node *dp = rinfo->of_node;
 -      u32 *val;
 +      const u32 *val;
  
        if (dp == NULL)
                return -ENODEV;
 -      val = (u32 *) get_property(dp, "ATY,RefCLK", NULL);
 +      val = get_property(dp, "ATY,RefCLK", NULL);
        if (!val || !*val) {
                printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
                return -EINVAL;
  
        rinfo->pll.ref_clk = (*val) / 10;
  
 -      val = (u32 *) get_property(dp, "ATY,SCLK", NULL);
 +      val = get_property(dp, "ATY,SCLK", NULL);
        if (val && *val)
                rinfo->pll.sclk = (*val) / 10;
  
 -      val = (u32 *) get_property(dp, "ATY,MCLK", NULL);
 +      val = get_property(dp, "ATY,MCLK", NULL);
        if (val && *val)
                rinfo->pll.mclk = (*val) / 10;
  
@@@ -2328,9 -2329,9 +2329,9 @@@ static int __devinit radeonfb_pci_regis
                /* -2 is special: means  ON on mobility chips and do not
                 * change on others
                 */
-               radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+               radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
        } else
-               radeonfb_pm_init(rinfo, default_dynclk);
+               radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
  
        pci_set_drvdata(pdev, info);
  
@@@ -2478,6 -2479,12 +2479,12 @@@ static int __init radeonfb_setup (char 
                        force_measure_pll = 1;
                } else if (!strncmp(this_opt, "ignore_edid", 11)) {
                        ignore_edid = 1;
+ #if defined(CONFIG_PM) && defined(CONFIG_X86)
+               } else if (!strncmp(this_opt, "force_sleep", 11)) {
+                       force_sleep = 1;
+               } else if (!strncmp(this_opt, "ignore_devlist", 14)) {
+                       ignore_devlist = 1;
+ #endif
                } else
                        mode_option = this_opt;
        }
@@@ -2533,3 -2540,9 +2540,9 @@@ module_param(panel_yres, int, 0)
  MODULE_PARM_DESC(panel_yres, "int: set panel yres");
  module_param(mode_option, charp, 0);
  MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+ #if defined(CONFIG_PM) && defined(CONFIG_X86)
+ module_param(force_sleep, bool, 0);
+ MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
+ module_param(ignore_devlist, bool, 0);
+ MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
+ #endif
  
  #include "ati_ids.h"
  
+ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
+ /*
+  * Workarounds for bugs in PC laptops:
+  * - enable D2 sleep in some IBM Thinkpads
+  * - special case for Samsung P35
+  *
+  * Whitelist by subsystem vendor/device because
+  * its the subsystem vendor's fault!
+  */
+ #if defined(CONFIG_PM) && defined(CONFIG_X86)
+ struct radeon_device_id {
+         const char *ident;                     /* (arbitrary) Name */
+         const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
+         const unsigned short subsystem_device; /* Subsystem Device ID */
+       const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
+       const reinit_function_ptr new_reinit_func;   /* changed reinit_func */
+ };
+ #define BUGFIX(model, sv, sd, pm, fn) { \
+       .ident = model, \
+       .subsystem_vendor = sv, \
+       .subsystem_device = sd, \
+       .pm_mode_modifier = pm, \
+       .new_reinit_func  = fn  \
+ }
+ static struct radeon_device_id radeon_workaround_list[] = {
+       BUGFIX("IBM Thinkpad R32",
+              PCI_VENDOR_ID_IBM, 0x1905,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R40",
+              PCI_VENDOR_ID_IBM, 0x0526,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R40",
+              PCI_VENDOR_ID_IBM, 0x0527,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R50/R51/T40/T41",
+              PCI_VENDOR_ID_IBM, 0x0531,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R51/T40/T41/T42",
+              PCI_VENDOR_ID_IBM, 0x0530,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T30",
+              PCI_VENDOR_ID_IBM, 0x0517,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T40p",
+              PCI_VENDOR_ID_IBM, 0x054d,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T42",
+              PCI_VENDOR_ID_IBM, 0x0550,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad X31/X32",
+              PCI_VENDOR_ID_IBM, 0x052f,
+              radeon_pm_d2, NULL),
+       BUGFIX("Samsung P35",
+              PCI_VENDOR_ID_SAMSUNG, 0xc00c,
+              radeon_pm_off, radeon_reinitialize_M10),
+       { .ident = NULL }
+ };
+ static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+ {
+       struct radeon_device_id *id;
+       for (id = radeon_workaround_list; id->ident != NULL; id++ )
+               if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
+                   (id->subsystem_device == rinfo->pdev->subsystem_device )) {
+                       /* we found a device that requires workaround */
+                       printk(KERN_DEBUG "radeonfb: %s detected"
+                              ", enabling workaround\n", id->ident);
+                       rinfo->pm_mode |= id->pm_mode_modifier;
+                       if (id->new_reinit_func != NULL)
+                               rinfo->reinit_func = id->new_reinit_func;
+                       return 1;
+               }
+       return 0;  /* not found */
+ }
+ #else  /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+ static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+ {
+         return 0;
+ }
+ #endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
  static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
  {
        u32 tmp;
@@@ -852,18 -945,26 +945,26 @@@ static void radeon_pm_setup_for_suspend
        /* because both INPLL and OUTPLL take the same lock, that's why. */
        tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
        OUTPLL( pllMCLK_MISC, tmp);
-       
-       /* AGP PLL control */
-       if (rinfo->family <= CHIP_FAMILY_RV280) {
-               OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
  
-               OUTREG(BUS_CNTL1,
-                      (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
-                      | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));   // 440BX
-       } else {
-               OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
-               OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+       /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
+        * and radeon chip dependent. Thus we only enable it on Mac for
+        * now (until we get more info on how to compute the correct
+        * value for various X86 bridges).
+        */
+ #ifdef CONFIG_PPC_PMAC
+       if (machine_is(powermac)) {
+               /* AGP PLL control */
+               if (rinfo->family <= CHIP_FAMILY_RV280) {
+                       OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
+                       OUTREG(BUS_CNTL1,
+                              (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
+                              | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));   // 440BX
+               } else {
+                       OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
+                       OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+               }
        }
+ #endif
  
        OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
                                  & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
@@@ -1167,7 -1268,7 +1268,7 @@@ static void radeon_pm_full_reset_sdram(
                          0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
                          0x31320032 };
  
 -              u32 *mrtable = default_mrtable;
 +              const u32 *mrtable = default_mrtable;
                int i, mrtable_size = ARRAY_SIZE(default_mrtable);
  
                mdelay(30);
                if (rinfo->of_node != NULL) {
                        int size;
  
 -                      mrtable = (u32 *)get_property(rinfo->of_node, "ATY,MRT", &size);
 +                      mrtable = get_property(rinfo->of_node, "ATY,MRT", &size);
                        if (mrtable)
                                mrtable_size = size >> 2;
                        else
@@@ -2713,7 -2814,7 +2814,7 @@@ static void radeonfb_early_resume(void 
  
  #endif /* CONFIG_PM */
  
- void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
+ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
  {
        /* Find PM registers in config space if any*/
        rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
        }
  
  #if defined(CONFIG_PM)
+ #if defined(CONFIG_PPC_PMAC)
        /* Check if we can power manage on suspend/resume. We can do
         * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
         * "Mac" cards, but that's all. We need more infos about what the
         * BIOS does tho. Right now, all this PM stuff is pmac-only for that
         * reason. --BenH
         */
-       /* Special case for Samsung P35 laptops
-        */
-       if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
-           (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
-           (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
-           (rinfo->pdev->subsystem_device == 0xc00c)) {
-               rinfo->reinit_func = radeon_reinitialize_M10;
-               rinfo->pm_mode |= radeon_pm_off;
-       }
- #if defined(CONFIG_PPC_PMAC)
        if (machine_is(powermac) && rinfo->of_node) {
                if (rinfo->is_mobility && rinfo->pm_reg &&
                    rinfo->family <= CHIP_FAMILY_RV250)
        }
  #endif /* defined(CONFIG_PPC_PMAC) */
  #endif /* defined(CONFIG_PM) */
+       if (ignore_devlist)
+               printk(KERN_DEBUG
+                      "radeonfb: skipping test for device workarounds\n");
+       else
+               radeon_apply_workarounds(rinfo);
+       if (force_sleep) {
+               printk(KERN_DEBUG
+                      "radeonfb: forcefully enabling D2 sleep mode\n");
+               rinfo->pm_mode |= radeon_pm_d2;
+       }
  }
  
  void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --combined drivers/video/offb.c
@@@ -17,7 -17,6 +17,6 @@@
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/mm.h>
- #include <linux/tty.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
  #include <linux/delay.h>
@@@ -410,30 -409,30 +409,30 @@@ static void __init offb_init_nodriver(s
        unsigned int flags, rsize, addr_prop = 0;
        unsigned long max_size = 0;
        u64 rstart, address = OF_BAD_ADDR;
 -      u32 *pp, *addrp, *up;
 +      const u32 *pp, *addrp, *up;
        u64 asize;
  
 -      pp = (u32 *)get_property(dp, "linux,bootx-depth", &len);
 +      pp = get_property(dp, "linux,bootx-depth", &len);
        if (pp == NULL)
 -              pp = (u32 *)get_property(dp, "depth", &len);
 +              pp = get_property(dp, "depth", &len);
        if (pp && len == sizeof(u32))
                depth = *pp;
  
 -      pp = (u32 *)get_property(dp, "linux,bootx-width", &len);
 +      pp = get_property(dp, "linux,bootx-width", &len);
        if (pp == NULL)
 -              pp = (u32 *)get_property(dp, "width", &len);
 +              pp = get_property(dp, "width", &len);
        if (pp && len == sizeof(u32))
                width = *pp;
  
 -      pp = (u32 *)get_property(dp, "linux,bootx-height", &len);
 +      pp = get_property(dp, "linux,bootx-height", &len);
        if (pp == NULL)
 -              pp = (u32 *)get_property(dp, "height", &len);
 +              pp = get_property(dp, "height", &len);
        if (pp && len == sizeof(u32))
                height = *pp;
  
 -      pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len);
 +      pp = get_property(dp, "linux,bootx-linebytes", &len);
        if (pp == NULL)
 -              pp = (u32 *)get_property(dp, "linebytes", &len);
 +              pp = get_property(dp, "linebytes", &len);
        if (pp && len == sizeof(u32))
                pitch = *pp;
        else
         * ranges and pick one that is both big enough and if possible encloses
         * the "address" property. If none match, we pick the biggest
         */
 -      up = (u32 *)get_property(dp, "linux,bootx-addr", &len);
 +      up = get_property(dp, "linux,bootx-addr", &len);
        if (up == NULL)
 -              up = (u32 *)get_property(dp, "address", &len);
 +              up = get_property(dp, "address", &len);
        if (up && len == sizeof(u32))
                addr_prop = *up;
  
@@@ -34,7 -34,6 +34,6 @@@
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/mm.h>
- #include <linux/tty.h>
  #include <linux/slab.h>
  #include <linux/delay.h>
  #include <linux/fb.h>
@@@ -278,9 -277,11 +277,11 @@@ static const struct riva_regs reg_templ
   */
  #define MIN_LEVEL 0x158
  #define MAX_LEVEL 0x534
+ #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
  
  static struct backlight_properties riva_bl_data;
  
+ /* Call with fb_info->bl_mutex held */
  static int riva_bl_get_level_brightness(struct riva_par *par,
                int level)
  {
        int nlevel;
  
        /* Get and convert the value */
-       mutex_lock(&info->bl_mutex);
-       nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
-       mutex_unlock(&info->bl_mutex);
+       nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
  
        if (nlevel < 0)
                nlevel = 0;
        return nlevel;
  }
  
- static int riva_bl_update_status(struct backlight_device *bd)
+ /* Call with fb_info->bl_mutex held */
+ static int __riva_bl_update_status(struct backlight_device *bd)
  {
        struct riva_par *par = class_get_devdata(&bd->class_dev);
        U032 tmp_pcrt, tmp_pmc;
        return 0;
  }
  
+ static int riva_bl_update_status(struct backlight_device *bd)
+ {
+       struct riva_par *par = class_get_devdata(&bd->class_dev);
+       struct fb_info *info = pci_get_drvdata(par->pdev);
+       int ret;
+       mutex_lock(&info->bl_mutex);
+       ret = __riva_bl_update_status(bd);
+       mutex_unlock(&info->bl_mutex);
+       return ret;
+ }
  static int riva_bl_get_brightness(struct backlight_device *bd)
  {
        return bd->props->brightness;
@@@ -339,6 -352,16 +352,16 @@@ static struct backlight_properties riva
        .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
  };
  
+ static void riva_bl_set_power(struct fb_info *info, int power)
+ {
+       mutex_lock(&info->bl_mutex);
+       up(&info->bl_dev->sem);
+       info->bl_dev->props->power = power;
+       __riva_bl_update_status(info->bl_dev);
+       down(&info->bl_dev->sem);
+       mutex_unlock(&info->bl_mutex);
+ }
  static void riva_bl_init(struct riva_par *par)
  {
        struct fb_info *info = pci_get_drvdata(par->pdev);
@@@ -419,6 -442,7 +442,7 @@@ static void riva_bl_exit(struct riva_pa
  #else
  static inline void riva_bl_init(struct riva_par *par) {}
  static inline void riva_bl_exit(struct riva_par *par) {}
+ static inline void riva_bl_set_power(struct fb_info *info, int power) {}
  #endif /* CONFIG_FB_RIVA_BACKLIGHT */
  
  /* ------------------------------------------------------------------------- *
@@@ -1337,16 -1361,7 +1361,7 @@@ static int rivafb_blank(int blank, stru
        SEQout(par, 0x01, tmp);
        CRTCout(par, 0x1a, vesa);
  
- #ifdef CONFIG_FB_RIVA_BACKLIGHT
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = blank;
-               info->bl_dev->props->update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
-       }
-       mutex_unlock(&info->bl_mutex);
- #endif
+       riva_bl_set_power(info, blank);
  
        NVTRACE_LEAVE();
  
@@@ -1816,13 -1831,14 +1831,13 @@@ static int __devinit riva_get_EDID_OF(s
        NVTRACE_ENTER();
        dp = pci_device_to_OF_node(pd);
        for (; dp != NULL; dp = dp->child) {
 -              disptype = (unsigned char *)get_property(dp, "display-type", NULL);
 +              disptype = get_property(dp, "display-type", NULL);
                if (disptype == NULL)
                        continue;
                if (strncmp(disptype, "LCD", 3) != 0)
                        continue;
                for (i = 0; propnames[i] != NULL; ++i) {
 -                      pedid = (unsigned char *)
 -                              get_property(dp, propnames[i], NULL);
 +                      pedid = get_property(dp, propnames[i], NULL);
                        if (pedid != NULL) {
                                par->EDID = pedid;
                                NVTRACE("LCD found.\n");
@@@ -2116,6 -2132,9 +2131,9 @@@ static int __devinit rivafb_probe(struc
  
        fb_destroy_modedb(info->monspecs.modedb);
        info->monspecs.modedb = NULL;
+       pci_set_drvdata(pd, info);
+       riva_bl_init(info->par);
        ret = register_framebuffer(info);
        if (ret < 0) {
                printk(KERN_ERR PFX
                goto err_iounmap_screen_base;
        }
  
-       pci_set_drvdata(pd, info);
        printk(KERN_INFO PFX
                "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
                info->fix.id,
                info->fix.smem_len / (1024 * 1024),
                info->fix.smem_start);
  
-       riva_bl_init(info->par);
        NVTRACE_LEAVE();
        return 0;
  
@@@ -39,7 -39,6 +39,6 @@@
  #define read_barrier_depends()  do { } while(0)
  
  #define set_mb(var, value)    do { var = value; mb(); } while (0)
- #define set_wmb(var, value)   do { var = value; wmb(); } while (0)
  
  #ifdef __KERNEL__
  #ifdef CONFIG_SMP
@@@ -169,6 -168,11 +168,6 @@@ extern u32 booke_wdt_enabled
  extern u32 booke_wdt_period;
  #endif /* CONFIG_BOOKE_WDT */
  
 -/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
 -extern unsigned char e2a(unsigned char);
 -extern unsigned char* strne2a(unsigned char *dest,
 -              const unsigned char *src, size_t n);
 -
  struct device_node;
  extern void note_scsi_host(struct device_node *, void *);
  
@@@ -215,8 -219,8 +214,8 @@@ __xchg_u32(volatile void *p, unsigned l
  "     stwcx.  %3,0,%2 \n\
        bne-    1b"
        ISYNC_ON_SMP
-       : "=&r" (prev), "=m" (*(volatile unsigned int *)p)
-       : "r" (p), "r" (val), "m" (*(volatile unsigned int *)p)
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
        : "cc", "memory");
  
        return prev;
@@@ -235,8 -239,8 +234,8 @@@ __xchg_u64(volatile void *p, unsigned l
  "     stdcx.  %3,0,%2 \n\
        bne-    1b"
        ISYNC_ON_SMP
-       : "=&r" (prev), "=m" (*(volatile unsigned long *)p)
-       : "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
        : "cc", "memory");
  
        return prev;
@@@ -294,8 -298,8 +293,8 @@@ __cmpxchg_u32(volatile unsigned int *p
        ISYNC_ON_SMP
        "\n\
  2:"
-       : "=&r" (prev), "=m" (*p)
-       : "r" (p), "r" (old), "r" (new), "m" (*p)
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
        : "cc", "memory");
  
        return prev;
@@@ -317,8 -321,8 +316,8 @@@ __cmpxchg_u64(volatile unsigned long *p
        ISYNC_ON_SMP
        "\n\
  2:"
-       : "=&r" (prev), "=m" (*p)
-       : "r" (p), "r" (old), "r" (new), "m" (*p)
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
        : "cc", "memory");
  
        return prev;