diff options
| author | Matthew Wilcox <willy@debian.org> | 2003-06-15 07:10:47 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-15 07:10:47 -0700 |
| commit | 9ff05b1bdf4cfa7dc41fe7d878a780d35196a87d (patch) | |
| tree | 612687a570b6f879cb292ec5e11d7dff99e389b3 /drivers/parisc | |
| parent | 20904d2543057fef12c928764922e1d190c2c455 (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/Kconfig | 23 | ||||
| -rw-r--r-- | drivers/parisc/dino.c | 4 | ||||
| -rw-r--r-- | drivers/parisc/eisa.c | 6 | ||||
| -rw-r--r-- | drivers/parisc/eisa_eeprom.c | 1 | ||||
| -rw-r--r-- | drivers/parisc/gsc.c | 3 | ||||
| -rw-r--r-- | drivers/parisc/gsc.h | 2 | ||||
| -rw-r--r-- | drivers/parisc/iosapic.c | 4 | ||||
| -rw-r--r-- | drivers/parisc/led.c | 175 | ||||
| -rw-r--r-- | drivers/parisc/superio.c | 10 |
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 */ |
