summary refs log tree commit diff
path: root/drivers/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/parisc')
-rw-r--r--drivers/parisc/dino.c30
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c2
-rw-r--r--drivers/parisc/lasi.c2
-rw-r--r--drivers/parisc/lba_pci.c115
-rw-r--r--drivers/parisc/led.c21
-rw-r--r--drivers/parisc/pdc_stable.c46
-rw-r--r--drivers/parisc/power.c12
8 files changed, 168 insertions, 64 deletions
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 5ab75334c579..216d1d859326 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -83,7 +83,8 @@
 ** bus number for each dino.
 */
 
-#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_card_dino(id)	((id)->hw_type == HPHW_A_DMA)
+#define is_cujo(id)		((id)->hversion == 0x682)
 
 #define DINO_IAR0		0x004
 #define DINO_IODC_ADDR		0x008
@@ -124,6 +125,7 @@
 
 #define DINO_IRQS 11		/* bits 0-10 are architected */
 #define DINO_IRR_MASK	0x5ff	/* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS+1)
 
 #define DINO_MASK_IRQ(x)	(1<<(x))
 
@@ -146,7 +148,7 @@ struct dino_device
 	unsigned long		txn_addr; /* EIR addr to generate interrupt */ 
 	u32			txn_data; /* EIR data assign to each dino */ 
 	u32 			imr;	  /* IRQ's which are enabled */ 
-	int			global_irq[12]; /* map IMR bit to global irq */
+	int			global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
 #ifdef DINO_DEBUG
 	unsigned int		dino_irr0; /* save most recent IRQ line stat */
 #endif
@@ -297,7 +299,7 @@ struct pci_port_ops dino_port_ops = {
 static void dino_disable_irq(unsigned int irq)
 {
 	struct dino_device *dino_dev = irq_desc[irq].handler_data;
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
 	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
 
@@ -309,7 +311,7 @@ static void dino_disable_irq(unsigned int irq)
 static void dino_enable_irq(unsigned int irq)
 {
 	struct dino_device *dino_dev = irq_desc[irq].handler_data;
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 	u32 tmp;
 
 	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -435,6 +437,21 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
 	dino_assign_irq(dino, irq, &dev->irq);
 }
 
+
+/*
+ * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
+ * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
+ */
+static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+{
+	u8 new_irq = dev->irq - 1;
+	printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
+			pci_name(dev), dev->irq, new_irq);
+	dev->irq = new_irq;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+
+
 static void __init
 dino_bios_init(void)
 {
@@ -666,7 +683,6 @@ dino_fixup_bus(struct pci_bus *bus)
 			printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
 #endif
 		} else {
-
 			/* Adjust INT_LINE for that busses region */
 			dino_assign_irq(dino_dev, dev->irq, &dev->irq);
 		}
@@ -872,7 +888,7 @@ static int __init dino_common_init(struct parisc_device *dev,
 
 	/* allocate I/O Port resource region */
 	res = &dino_dev->hba.io_space;
-	if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
+	if (!is_cujo(&dev->id)) {
 		res->name = "Dino I/O Port";
 	} else {
 		res->name = "Cujo I/O Port";
@@ -927,7 +943,7 @@ static int __init dino_probe(struct parisc_device *dev)
 	if (is_card_dino(&dev->id)) {
 		version = "3.x (card mode)";
 	} else {
-		if(dev->id.hversion == 0x680) {
+		if (!is_cujo(&dev->id)) {
 			if (dev->id.hversion_rev < 4) {
 				version = dino_vers[dev->id.hversion_rev];
 			}
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 6362bf99eff6..3d94d86c1c9f 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -57,7 +57,7 @@
 
 static DEFINE_SPINLOCK(eisa_irq_lock);
 
-void __iomem *eisa_eeprom_addr;
+void __iomem *eisa_eeprom_addr __read_mostly;
 
 /* We can only have one EISA adapter in the system because neither
  * implementation can be flexed.
@@ -141,7 +141,7 @@ static int slave_mask;
  * in the furure. 
  */
 /* irq 13,8,2,1,0 must be edge */
-static unsigned int eisa_irq_level; /* default to edge triggered */
+static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered */
 
 
 /* called by free irq */
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 3a1b4826e5c1..e13aafa70bf5 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -48,7 +48,7 @@ static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
 }
 
 static ssize_t eisa_eeprom_read(struct file * file,
-			      char *buf, size_t count, loff_t *ppos )
+			      char __user *buf, size_t count, loff_t *ppos )
 {
 	unsigned char *tmp;
 	ssize_t ret;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index a8c20396ffbe..2b3ba1dcf332 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -150,7 +150,7 @@ void __init lasi_led_init(unsigned long lasi_hpa)
  * 
  */
 
-static unsigned long lasi_power_off_hpa;
+static unsigned long lasi_power_off_hpa __read_mostly;
 
 static void lasi_power_off(void)
 {
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 5e495dcbc58a..cbae8c8963fa 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -167,7 +167,7 @@
 
 /* non-postable I/O port space, densely packed */
 #define LBA_PORT_BASE	(PCI_F_EXTEND | 0xfee00000UL)
-static void __iomem *astro_iop_base;
+static void __iomem *astro_iop_base __read_mostly;
 
 #define ELROY_HVERS	0x782
 #define MERCURY_HVERS	0x783
@@ -695,11 +695,71 @@ lba_claim_dev_resources(struct pci_dev *dev)
 		}
 	}
 }
+
+
+/*
+ * truncate_pat_collision:  Deal with overlaps or outright collisions
+ *			between PAT PDC reported ranges.
+ *
+ *   Broken PA8800 firmware will report lmmio range that
+ *   overlaps with CPU HPA. Just truncate the lmmio range.
+ *
+ *   BEWARE: conflicts with this lmmio range may be an
+ *   elmmio range which is pointing down another rope.
+ *
+ *  FIXME: only deals with one collision per range...theoretically we
+ *  could have several. Supporting more than one collision will get messy.
+ */
+static unsigned long
+truncate_pat_collision(struct resource *root, struct resource *new)
+{
+	unsigned long start = new->start;
+	unsigned long end = new->end;
+	struct resource *tmp = root->child;
+
+	if (end <= start || start < root->start || !tmp)
+		return 0;
+
+	/* find first overlap */
+	while (tmp && tmp->end < start)
+		tmp = tmp->sibling;
+
+	/* no entries overlap */
+	if (!tmp)  return 0;
+
+	/* found one that starts behind the new one
+	** Don't need to do anything.
+	*/
+	if (tmp->start >= end) return 0;
+
+	if (tmp->start <= start) {
+		/* "front" of new one overlaps */
+		new->start = tmp->end + 1;
+
+		if (tmp->end >= end) {
+			/* AACCKK! totally overlaps! drop this range. */
+			return 1;
+		}
+	} 
+
+	if (tmp->end < end ) {
+		/* "end" of new one overlaps */
+		new->end = tmp->start - 1;
+	}
+
+	printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
+					"to [%lx,%lx]\n",
+			start, end,
+			new->start, new->end );
+
+	return 0;	/* truncation successful */
+}
+
 #else
-#define lba_claim_dev_resources(dev)
+#define lba_claim_dev_resources(dev) do { } while (0)
+#define truncate_pat_collision(r,n)  (0)
 #endif
 
-
 /*
 ** The algorithm is generic code.
 ** But it needs to access local data structures to get the IRQ base.
@@ -747,6 +807,9 @@ lba_fixup_bus(struct pci_bus *bus)
 			lba_dump_res(&ioport_resource, 2);
 			BUG();
 		}
+		/* advertize Host bridge resources to PCI bus */
+		bus->resource[0] = &(ldev->hba.io_space);
+		i = 1;
 
 		if (ldev->hba.elmmio_space.start) {
 			err = request_resource(&iomem_resource,
@@ -760,23 +823,35 @@ lba_fixup_bus(struct pci_bus *bus)
 
 				/* lba_dump_res(&iomem_resource, 2); */
 				/* BUG(); */
-			}
+			} else
+				bus->resource[i++] = &(ldev->hba.elmmio_space);
 		}
 
-		err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
-		if (err < 0) {
-			/*   FIXME  overlaps with elmmio will fail here.
-			 *   Need to prune (or disable) the distributed range.
-			 *
-			 *   BEWARE: conflicts with this lmmio range may be
-			 *   elmmio range which is pointing down another rope.
-			 */
-
-			printk("FAILED: lba_fixup_bus() request for "
+
+		/*   Overlaps with elmmio can (and should) fail here.
+		 *   We will prune (or ignore) the distributed range.
+		 *
+		 *   FIXME: SBA code should register all elmmio ranges first.
+		 *      that would take care of elmmio ranges routed
+		 *	to a different rope (already discovered) from
+		 *	getting registered *after* LBA code has already
+		 *	registered it's distributed lmmio range.
+		 */
+		if (truncate_pat_collision(&iomem_resource,
+				       	&(ldev->hba.lmmio_space))) {
+
+			printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+					ldev->hba.lmmio_space.start,
+					ldev->hba.lmmio_space.end);
+		} else {
+			err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
+			if (err < 0) {
+				printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
 					"lmmio_space [%lx/%lx]\n",
 					ldev->hba.lmmio_space.start,
 					ldev->hba.lmmio_space.end);
-			/* lba_dump_res(&iomem_resource, 2); */
+			} else
+				bus->resource[i++] = &(ldev->hba.lmmio_space);
 		}
 
 #ifdef CONFIG_64BIT
@@ -791,18 +866,10 @@ lba_fixup_bus(struct pci_bus *bus)
 				lba_dump_res(&iomem_resource, 2);
 				BUG();
 			}
+			bus->resource[i++] = &(ldev->hba.gmmio_space);
 		}
 #endif
 
-		/* advertize Host bridge resources to PCI bus */
-		bus->resource[0] = &(ldev->hba.io_space);
-		bus->resource[1] = &(ldev->hba.lmmio_space);
-		i=2;
-		if (ldev->hba.elmmio_space.start)
-			bus->resource[i++] = &(ldev->hba.elmmio_space);
-		if (ldev->hba.gmmio_space.start)
-			bus->resource[i++] = &(ldev->hba.gmmio_space);
-			
 	}
 
 	list_for_each(ln, &bus->devices) {
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 95bd07b8b61b..3627a2d7f79f 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -3,7 +3,7 @@
  *
  *      (c) Copyright 2000 Red Hat Software
  *      (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
- *      (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
+ *      (c) Copyright 2001-2005 Helge Deller <deller@gmx.de>
  *      (c) Copyright 2001 Randolph Chung <tausq@debian.org>
  *
  *      This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/utsname.h>
+#include <linux/capability.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
@@ -56,13 +57,13 @@
    relatively large amount of CPU time, some of the calculations can be 
    turned off with the following variables (controlled via procfs) */
 
-static int led_type = -1;
+static int led_type __read_mostly = -1;
 static unsigned char lastleds;	/* LED state from most recent update */
-static unsigned int led_heartbeat = 1;
-static unsigned int led_diskio = 1;
-static unsigned int led_lanrxtx = 1;
-static char lcd_text[32];
-static char lcd_text_default[32];
+static unsigned int led_heartbeat __read_mostly = 1;
+static unsigned int led_diskio    __read_mostly = 1;
+static unsigned int led_lanrxtx   __read_mostly = 1;
+static char lcd_text[32]          __read_mostly;
+static char lcd_text_default[32]  __read_mostly;
 
 
 static struct workqueue_struct *led_wq;
@@ -108,7 +109,7 @@ struct pdc_chassis_lcd_info_ret_block {
 /* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's 
  * HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */
 static struct pdc_chassis_lcd_info_ret_block
-lcd_info __attribute__((aligned(8))) =
+lcd_info __attribute__((aligned(8))) __read_mostly =
 {
 	.model =		DISPLAY_MODEL_LCD,
 	.lcd_width =		16,
@@ -144,7 +145,7 @@ static int start_task(void)
 device_initcall(start_task);
 
 /* ptr to LCD/LED-specific function */
-static void (*led_func_ptr) (unsigned char);
+static void (*led_func_ptr) (unsigned char) __read_mostly;
 
 #ifdef CONFIG_PROC_FS
 static int led_proc_read(char *page, char **start, off_t off, int count, 
@@ -347,7 +348,7 @@ static void led_LCD_driver(unsigned char leds)
    ** 
    ** led_get_net_activity()
    ** 
-   ** calculate if there was TX- or RX-troughput on the network interfaces
+   ** calculate if there was TX- or RX-throughput on the network interfaces
    ** (analog to dev_get_info() from net/core/dev.c)
    **   
  */
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 273a74179720..42a3c54e8e6c 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -42,9 +42,9 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>		/* for capable() */
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/capability.h>
 #include <linux/ctype.h>
 #include <linux/sysfs.h>
 #include <linux/kobject.h>
@@ -56,7 +56,7 @@
 #include <asm/uaccess.h>
 #include <asm/hardware.h>
 
-#define PDCS_VERSION	"0.09"
+#define PDCS_VERSION	"0.10"
 
 #define PDCS_ADDR_PPRI	0x00
 #define PDCS_ADDR_OSID	0x40
@@ -70,7 +70,7 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PDCS_VERSION);
 
-static unsigned long pdcs_size = 0;
+static unsigned long pdcs_size __read_mostly;
 
 /* This struct defines what we need to deal with a parisc pdc path entry */
 struct pdcspath_entry {
@@ -194,7 +194,8 @@ pdcspath_store(struct pdcspath_entry *entry)
 		return -EIO;
 	}
 		
-	entry->ready = 1;
+	/* kobject is already registered */
+	entry->ready = 2;
 	
 	DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
 	
@@ -653,15 +654,21 @@ pdcs_register_pathentries(void)
 {
 	unsigned short i;
 	struct pdcspath_entry *entry;
+	int err;
 	
 	for (i = 0; (entry = pdcspath_entries[i]); i++) {
 		if (pdcspath_fetch(entry) < 0)
 			continue;
 
-		kobject_set_name(&entry->kobj, "%s", entry->name);
+		if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
+			return err;
 		kobj_set_kset_s(entry, paths_subsys);
-		kobject_register(&entry->kobj);
-
+		if ((err = kobject_register(&entry->kobj)))
+			return err;
+		
+		/* kobject is now registered */
+		entry->ready = 2;
+		
 		if (!entry->dev)
 			continue;
 
@@ -675,14 +682,14 @@ pdcs_register_pathentries(void)
 /**
  * pdcs_unregister_pathentries - Routine called when unregistering the module.
  */
-static inline void __exit
+static inline void
 pdcs_unregister_pathentries(void)
 {
 	unsigned short i;
 	struct pdcspath_entry *entry;
 	
 	for (i = 0; (entry = pdcspath_entries[i]); i++)
-		if (entry->ready)
+		if (entry->ready >= 2)
 			kobject_unregister(&entry->kobj);	
 }
 
@@ -704,7 +711,7 @@ pdc_stable_init(void)
 
 	/* For now we'll register the pdc subsys within this driver */
 	if ((rc = firmware_register(&pdc_subsys)))
-		return rc;
+		goto fail_firmreg;
 
 	/* Don't forget the info entry */
 	for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
@@ -713,12 +720,25 @@ pdc_stable_init(void)
 	
 	/* register the paths subsys as a subsystem of pdc subsys */
 	kset_set_kset_s(&paths_subsys, pdc_subsys);
-	subsystem_register(&paths_subsys);
+	if ((rc= subsystem_register(&paths_subsys)))
+		goto fail_subsysreg;
 
 	/* now we create all "files" for the paths subsys */
-	pdcs_register_pathentries();
+	if ((rc = pdcs_register_pathentries()))
+		goto fail_pdcsreg;
+
+	return rc;
 	
-	return 0;
+fail_pdcsreg:
+	pdcs_unregister_pathentries();
+	subsystem_unregister(&paths_subsys);
+	
+fail_subsysreg:
+	firmware_unregister(&pdc_subsys);
+	
+fail_firmreg:
+	printk(KERN_INFO "PDC Stable Storage bailing out\n");
+	return rc;
 }
 
 static void __exit
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index ff75e9296df9..54b2b7f20b96 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -2,7 +2,7 @@
  * linux/arch/parisc/kernel/power.c
  * HP PARISC soft power switch support driver
  *
- * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de>
  * All rights reserved.
  *
  *
@@ -102,7 +102,7 @@ static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL);
 
 static void poweroff(void)
 {
-	static int powering_off;
+	static int powering_off __read_mostly;
 
 	if (powering_off)
 		return;
@@ -113,7 +113,7 @@ static void poweroff(void)
 
 
 /* local time-counter for shutdown */
-static int shutdown_timer;
+static int shutdown_timer __read_mostly;
 
 /* check, give feedback and start shutdown after one second */
 static void process_shutdown(void)
@@ -139,7 +139,7 @@ static void process_shutdown(void)
 DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
 
 /* soft power switch enabled/disabled */
-int pwrsw_enabled = 1;
+int pwrsw_enabled __read_mostly = 1;
 
 /*
  * On gecko style machines (e.g. 712/xx and 715/xx) 
@@ -149,7 +149,7 @@ int pwrsw_enabled = 1;
  */
 static void gecko_tasklet_func(unsigned long unused)
 {
-	if (!pwrsw_enabled)
+	if (unlikely(!pwrsw_enabled))
 		return;
 
 	if (__getDIAG(25) & 0x80000000) {
@@ -173,7 +173,7 @@ static void polling_tasklet_func(unsigned long soft_power_reg)
 {
         unsigned long current_status;
 	
-	if (!pwrsw_enabled)
+	if (unlikely(!pwrsw_enabled))
 		return;
 
 	current_status = gsc_readl(soft_power_reg);