summaryrefslogtreecommitdiff
path: root/drivers/parisc
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@debian.org>2003-06-15 07:10:47 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-06-15 07:10:47 -0700
commit9ff05b1bdf4cfa7dc41fe7d878a780d35196a87d (patch)
tree612687a570b6f879cb292ec5e11d7dff99e389b3 /drivers/parisc
parent20904d2543057fef12c928764922e1d190c2c455 (diff)
[PATCH] parisc arch update
This update covers a lot of changes to arch/parisc and parisc-specific drivers. - irq_return_t changes - more work on the module loader (James Bottomley) - rewrite of led.c by Helge Deller - many miscellaneous updates
Diffstat (limited to 'drivers/parisc')
-rw-r--r--drivers/parisc/Kconfig23
-rw-r--r--drivers/parisc/dino.c4
-rw-r--r--drivers/parisc/eisa.c6
-rw-r--r--drivers/parisc/eisa_eeprom.c1
-rw-r--r--drivers/parisc/gsc.c3
-rw-r--r--drivers/parisc/gsc.h2
-rw-r--r--drivers/parisc/iosapic.c4
-rw-r--r--drivers/parisc/led.c175
-rw-r--r--drivers/parisc/superio.c10
9 files changed, 118 insertions, 110 deletions
diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
index 3a6f314ddaea..ac0860df198b 100644
--- a/drivers/parisc/Kconfig
+++ b/drivers/parisc/Kconfig
@@ -125,4 +125,27 @@ config CHASSIS_LCD_LED
If unsure, say Y.
+config HOTPLUG
+ bool "Support for hot-pluggable devices"
+ ---help---
+ Say Y here if you want to plug devices into your computer while
+ the system is running, and be able to use them quickly. In many
+ cases, the devices can likewise be unplugged at any time too.
+
+ One well known example of this is PCMCIA- or PC-cards, credit-card
+ size devices such as network cards, modems or hard drives which are
+ plugged into slots found on all modern laptop computers. Another
+ example, used on modern desktops as well as laptops, is USB.
+
+ Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
+ software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+ Then your kernel will automatically call out to a user mode "policy
+ agent" (/sbin/hotplug) to load modules and set up software needed
+ to use devices as you hotplug them.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+
endmenu
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 38d480f19920..49bac9db320f 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -381,7 +381,7 @@ static struct irq_region_ops dino_irq_ops = {
* ilr_loop counter is a kluge to prevent a "stuck" IRQ line from
* wedging the CPU. Could be removed or made optional at some point.
*/
-static void
+static irqreturn_t
dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
{
struct dino_device *dino_dev = DINO_DEV(intr_dev);
@@ -441,7 +441,9 @@ ilr_again:
if (--ilr_loop > 0)
goto ilr_again;
printk("Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask);
+ return IRQ_NONE;
}
+ return IRQ_HANDLED;
}
static int dino_choose_irq(struct parisc_device *dev)
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index afd2267104ba..547ef6adffe9 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -213,7 +213,7 @@ static struct irq_region eisa_irq_region = {
.action = action,
};
-static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
+static irqreturn_t eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
{
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
@@ -262,11 +262,13 @@ static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
eisa_out8(master_mask, 0x21);
}
spin_unlock_irqrestore(&eisa_irq_lock, flags);
+ return IRQ_HANDLED;
}
-static void dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
+static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
{
printk(KERN_ALERT "eisa: uhh, irq2?\n");
+ return IRQ_HANDLED;
}
static void init_eisa_pic(void)
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index bdd34f5f609f..bda206c1393f 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
+#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/eisa_eeprom.h>
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index f5a921a6db1b..6f78bdb4180a 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -79,7 +79,7 @@ EXPORT_SYMBOL(gsc_claim_irq);
#define GSC_MASK_IRQ(x) (1<<(GSC_FIX_IRQ(x)))
/* Common interrupt demultiplexer used by Asp, Lasi & Wax. */
-void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
+irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
{
unsigned long irq;
struct busdevice *busdev = (struct busdevice *) dev;
@@ -101,6 +101,7 @@ void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
do_irq_mask(irq, busdev->busdev_region, regs);
}
+ return IRQ_HANDLED;
}
static void
diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h
index 865976ea99c1..cd05a1fad17b 100644
--- a/drivers/parisc/gsc.h
+++ b/drivers/parisc/gsc.h
@@ -43,4 +43,4 @@ int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev);
extern int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
extern int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
-void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
+irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index d5ca79f00343..89d1484e9a73 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -605,7 +605,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
}
-static void
+static irqreturn_t
iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct vector_info *vi = (struct vector_info *)dev_id;
@@ -623,6 +623,8 @@ iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
** I/O SAPIC must always issue EOI.
*/
IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
+
+ return IRQ_HANDLED;
}
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index ace3cbd21dbb..69a53774882d 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-2002 Helge Deller <deller@gmx.de>
+ * (c) Copyright 2001-2003 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
@@ -13,7 +13,7 @@
*
* TODO:
* - speed-up calculations with inlined assembler
- * - interface to write to second row of LCD from /proc
+ * - interface to write to second row of LCD from /proc (if technically possible)
*/
#include <linux/config.h>
@@ -22,10 +22,11 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/ioport.h>
-#include <linux/bitops.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/reboot.h>
@@ -59,10 +60,6 @@ static char lcd_text[32];
#endif
-#define CALC_ADD(val, comp, add) \
- (val<=(comp/8) ? add/16 : val<=(comp/4) ? add/8 : val<=(comp/2) ? add/4 : add)
-
-
struct lcd_block {
unsigned char command; /* stores the command byte */
unsigned char on; /* value for turning LED on */
@@ -341,93 +338,81 @@ static void led_LCD_driver(unsigned char leds)
/*
**
- ** led_get_net_stats()
+ ** led_get_net_activity()
**
- ** calculate the TX- & RX-troughput on the network interfaces in
- ** the system for usage in the LED code
- **
+ ** calculate if there was TX- or RX-troughput on the network interfaces
** (analog to dev_get_info() from net/core/dev.c)
**
*/
-static unsigned long led_net_rx_counter, led_net_tx_counter;
-
-static void led_get_net_stats(int addvalue)
+static __inline__ int led_get_net_activity(void)
{
-#ifdef CONFIG_NET
+#ifndef CONFIG_NET
+ return 0;
+#else
static unsigned long rx_total_last, tx_total_last;
unsigned long rx_total, tx_total;
struct net_device *dev;
- struct net_device_stats *stats;
+ int retval;
rx_total = tx_total = 0;
- /* we are running as a tasklet, so locking dev_base
+ /* we are running as tasklet, so locking dev_base
* for reading should be OK */
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (dev->get_stats) {
- stats = dev->get_stats(dev);
- rx_total += stats->rx_packets;
- tx_total += stats->tx_packets;
- }
+ for (dev = dev_base; dev; dev = dev->next) {
+ struct net_device_stats *stats;
+ struct in_device *in_dev = __in_dev_get(dev);
+ if (!in_dev || !in_dev->ifa_list)
+ continue;
+ if (LOOPBACK(in_dev->ifa_list->ifa_local))
+ continue;
+ if (!dev->get_stats)
+ continue;
+ stats = dev->get_stats(dev);
+ rx_total += stats->rx_packets;
+ tx_total += stats->tx_packets;
}
read_unlock(&dev_base_lock);
- rx_total -= rx_total_last;
- tx_total -= tx_total_last;
-
- if (rx_total)
- led_net_rx_counter += CALC_ADD(rx_total, tx_total, addvalue);
-
- if (tx_total)
- led_net_tx_counter += CALC_ADD(tx_total, rx_total, addvalue);
-
- rx_total_last += rx_total;
- tx_total_last += tx_total;
+ retval = 0;
+
+ if (rx_total != rx_total_last) {
+ rx_total_last = rx_total;
+ retval |= LED_LAN_RCV;
+ }
+
+ if (tx_total != tx_total_last) {
+ tx_total_last = tx_total;
+ retval |= LED_LAN_TX;
+ }
+
+ return retval;
#endif
}
/*
**
- ** led_get_diskio_stats()
+ ** led_get_diskio_activity()
**
- ** calculate the disk-io througput in the system
- ** (analog to linux/fs/proc/proc_misc.c)
+ ** calculate if there was disk-io in the system
**
*/
-static unsigned long led_diskio_counter;
-
-static void led_get_diskio_stats(int addvalue)
+static __inline__ int led_get_diskio_activity(void)
{
- static unsigned int diskio_total_last, diskio_max;
- int major, disk, total;
+ static unsigned long last_pgpgin, last_pgpgout;
+ struct page_state pgstat;
+ int changed;
- total = 0;
-#if 0
- /*
- * this section will no longer work in 2.5, as we no longer
- * have either kstat.dk_drive nor DK_MAX_*. It can probably
- * be rewritten to use the per-disk statistics now kept in the
- * gendisk, but since I have no HP machines to test it on, I'm
- * not really up to that. ricklind@us.ibm.com 11/7/02
- */
- for (major = 0; major < DK_MAX_MAJOR; major++) {
- for (disk = 0; disk < DK_MAX_DISK; disk++)
- total += dkstat.drive[major][disk];
- }
- total -= diskio_total_last;
-
- if (total) {
- if (total >= diskio_max) {
- led_diskio_counter += addvalue;
- diskio_max = total; /* new maximum value found */
- } else
- led_diskio_counter += CALC_ADD(total, diskio_max, addvalue);
- }
-#endif
+ get_full_page_state(&pgstat); /* get no of sectors in & out */
+
+ /* Just use a very simple calculation here. Do not care about overflow,
+ since we only want to know if there was activity or not. */
+ changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
+ last_pgpgin = pgstat.pgpgin;
+ last_pgpgout = pgstat.pgpgout;
- diskio_total_last += total;
+ return (changed ? LED_DISK_IO : 0);
}
@@ -443,16 +428,23 @@ static void led_get_diskio_stats(int addvalue)
- optimizations
*/
-static unsigned char currentleds; /* stores current value of the LEDs */
-
#define HEARTBEAT_LEN (HZ*6/100)
#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
+#if HZ==100
+ #define NORMALIZED_COUNT(count) (count)
+#else
+ #warning "Untested situation HZ != 100 !!"
+ #define NORMALIZED_COUNT(count) (count/(HZ/100))
+#endif
+
static void led_tasklet_func(unsigned long unused)
{
- static unsigned int count, count_HZ;
static unsigned char lastleds;
+ unsigned char currentleds; /* stores current value of the LEDs */
+ static unsigned long count; /* static incremented value, not wrapped */
+ static unsigned long count_HZ; /* counter in range 0..HZ */
/* exit if not initialized */
if (!led_func_ptr)
@@ -463,6 +455,8 @@ static void led_tasklet_func(unsigned long unused)
if (++count_HZ == HZ)
count_HZ = 0;
+ currentleds = lastleds;
+
if (led_heartbeat)
{
/* flash heartbeat-LED like a real heart (2 x short then a long delay) */
@@ -473,42 +467,25 @@ static void led_tasklet_func(unsigned long unused)
currentleds &= ~LED_HEARTBEAT;
}
- /* gather network and diskio statistics and flash LEDs respectively */
-
- if (led_lanrxtx)
+ /* look for network activity and flash LEDs respectively */
+ if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
{
- if ((count & 31) == 0)
- led_get_net_stats(30);
-
- if (led_net_rx_counter) {
- led_net_rx_counter--;
- currentleds |= LED_LAN_RCV;
- }
- else
- currentleds &= ~LED_LAN_RCV;
-
- if (led_net_tx_counter) {
- led_net_tx_counter--;
- currentleds |= LED_LAN_TX;
- }
- else
- currentleds &= ~LED_LAN_TX;
+ currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
+ currentleds |= led_get_net_activity();
}
- if (led_diskio)
+ /* avoid to calculate diskio-stats at same irq as netio-stats */
+ if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
{
- /* avoid to calculate diskio-stats at same irq as netio-stats ! */
- if ((count & 31) == 15)
- led_get_diskio_stats(30);
-
- if (led_diskio_counter) {
- led_diskio_counter--;
- currentleds |= LED_DISK_IO;
- }
- else
- currentleds &= ~LED_DISK_IO;
+ currentleds &= ~LED_DISK_IO;
+ currentleds |= led_get_diskio_activity();
}
+ /* blink all LEDs twice a second if we got an Oops (HPMC) */
+ if (oops_in_progress) {
+ currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
+ }
+
/* update the LCD/LEDs */
if (currentleds != lastleds) {
led_func_ptr(currentleds);
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 9c88a673fd9d..d8c98ea0c581 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -90,7 +90,7 @@ superio_inform_irq(int irq)
sio_dev.iosapic_irq = irq;
}
-static void
+static irqreturn_t
superio_interrupt(int irq, void *devp, struct pt_regs *regs)
{
struct superio_device *sio = (struct superio_device *)devp;
@@ -107,7 +107,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
/* HACK: need to investigate why this happens if SMP enabled */
BUG(); /* This shouldn't happen */
#endif
- return;
+ return IRQ_HANDLED;
}
/* Check to see which device is interrupting */
@@ -117,7 +117,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
if (local_irq == 2 || local_irq > 7) {
printk(KERN_ERR "SuperIO: slave interrupted!\n");
BUG();
- return;
+ return IRQ_HANDLED;
}
if (local_irq == 7) {
@@ -128,7 +128,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
results = inb(IC_PIC1+0);
if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
- return;
+ return IRQ_HANDLED;
}
}
@@ -141,7 +141,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
/* set EOI */
outb((OCW2_SEOI|local_irq),IC_PIC1 + 0);
- return;
+ return IRQ_HANDLED;
}
/* Initialize Super I/O device */