diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-26 12:48:06 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-26 12:48:06 -0800 |
commit | b0138a6cb7923a997d278b47c176778534d1095b (patch) | |
tree | 4fcb8822a69631baba568e4e1942847747123887 /drivers | |
parent | 6572d6d7d0f965dda19d02af804ed3ae4b3bf1fc (diff) | |
parent | 1055a8af093fea7490445bd15cd671020e542035 (diff) | |
download | kernel_samsung_smdk4412-b0138a6cb7923a997d278b47c176778534d1095b.zip kernel_samsung_smdk4412-b0138a6cb7923a997d278b47c176778534d1095b.tar.gz kernel_samsung_smdk4412-b0138a6cb7923a997d278b47c176778534d1095b.tar.bz2 |
Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6: (78 commits)
[PARISC] Use symbolic last syscall in __NR_Linux_syscalls
[PARISC] Add missing statfs64 and fstatfs64 syscalls
Revert "[PARISC] Optimize TLB flush on SMP systems"
[PARISC] Compat signal fixes for 64-bit parisc
[PARISC] Reorder syscalls to match unistd.h
Revert "[PATCH] make kernel/signal.c:kill_proc_info() static"
[PARISC] fix sys_rt_sigqueueinfo
[PARISC] fix section mismatch warnings in harmony sound driver
[PARISC] do not export get_register/set_register
[PARISC] add ENTRY()/ENDPROC() and simplify assembly of HP/UX emulation code
[PARISC] convert to use CONFIG_64BIT instead of __LP64__
[PARISC] use CONFIG_64BIT instead of __LP64__
[PARISC] add ASM_EXCEPTIONTABLE_ENTRY() macro
[PARISC] more ENTRY(), ENDPROC(), END() conversions
[PARISC] fix ENTRY() and ENDPROC() for 64bit-parisc
[PARISC] Fixes /proc/cpuinfo cache output on B160L
[PARISC] implement standard ENTRY(), END() and ENDPROC()
[PARISC] kill ENTRY_SYS_CPUS
[PARISC] clean up debugging printks in smp.c
[PARISC] factor syscall_restart code out of do_signal
...
Fix conflict in include/linux/sched.h due to kill_proc_info() being made
publicly available to PARISC again.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/agp/parisc-agp.c | 2 | ||||
-rw-r--r-- | drivers/net/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/lasi_82596.c | 34 | ||||
-rw-r--r-- | drivers/parisc/hppb.c | 14 | ||||
-rw-r--r-- | drivers/parisc/iosapic_private.h | 2 | ||||
-rw-r--r-- | drivers/parisc/lba_pci.c | 90 | ||||
-rw-r--r-- | drivers/parisc/led.c | 14 | ||||
-rw-r--r-- | drivers/parisc/power.c | 201 | ||||
-rw-r--r-- | drivers/parisc/sba_iommu.c | 4 | ||||
-rw-r--r-- | drivers/serial/mux.c | 167 |
10 files changed, 297 insertions, 237 deletions
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 36d07e3..3c8f3d6 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -236,7 +236,7 @@ static int __init agp_ioc_init(void __iomem *ioc_regs) { struct _parisc_agp_info *info = &parisc_agp_info; - u64 *iova_base, *io_pdir, io_tlb_ps; + u64 iova_base, *io_pdir, io_tlb_ps; int io_tlb_shift; printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n"); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9d5c083..38ac679 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -430,10 +430,10 @@ config HPLANCE config LASI_82596 tristate "Lasi ethernet" - depends on NET_ETHERNET && PARISC && GSC_LASI + depends on NET_ETHERNET && GSC help - Say Y here to support the on-board Intel 82596 ethernet controller - built into Hewlett-Packard PA-RISC machines. + Say Y here to support the builtin Intel 82596 ethernet controller + found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. config MIPS_JAZZ_SONIC tristate "MIPS JAZZ onboard SONIC Ethernet support" diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index ea392f2..452863d 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -384,7 +384,7 @@ struct i596_private { struct device *dev; }; -static char init_setup[] = +static const char init_setup[] = { 0x8E, /* length, prefetch on */ 0xC8, /* fifo to 8, monitor off */ @@ -683,7 +683,7 @@ static int init_i596_mem(struct net_device *dev) enable_irq(dev->irq); /* enable IRQs from LAN */ DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); - memcpy(lp->cf_cmd.i596_config, init_setup, 14); + memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup)); lp->cf_cmd.cmd.command = CmdConfigure; CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); @@ -1156,32 +1156,12 @@ static int __devinit i82596_probe(struct net_device *dev, dma_addr_t dma_addr; /* This lot is ensure things have been cache line aligned. */ - if (sizeof(struct i596_rfd) != 32) { - printk("82596: sizeof(struct i596_rfd) = %d\n", - (int)sizeof(struct i596_rfd)); - return -ENODEV; - } - if ((sizeof(struct i596_rbd) % 32) != 0) { - printk("82596: sizeof(struct i596_rbd) = %d\n", - (int)sizeof(struct i596_rbd)); - return -ENODEV; - } - if ((sizeof(struct tx_cmd) % 32) != 0) { - printk("82596: sizeof(struct tx_cmd) = %d\n", - (int)sizeof(struct tx_cmd)); - return -ENODEV; - } - if (sizeof(struct i596_tbd) != 32) { - printk("82596: sizeof(struct i596_tbd) = %d\n", - (int)sizeof(struct i596_tbd)); - return -ENODEV; - } + BUILD_BUG_ON(sizeof(struct i596_rfd) != 32); + BUILD_BUG_ON(sizeof(struct i596_rbd) & 31); + BUILD_BUG_ON(sizeof(struct tx_cmd) & 31); + BUILD_BUG_ON(sizeof(struct i596_tbd) != 32); #ifndef __LP64__ - if (sizeof(struct i596_private) > 4096) { - printk("82596: sizeof(struct i596_private) = %d\n", - (int)sizeof(struct i596_private)); - return -ENODEV; - } + BUILD_BUG_ON(sizeof(struct i596_private) > 4096); #endif if (!dev->base_addr || !dev->irq) diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 07dc2b6..9bb4db5 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -10,10 +10,6 @@ ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** -** This Driver currently only supports the console (port 0) on the MUX. -** Additional work will be needed on this driver to enable the full -** functionality of the MUX. -** */ #include <linux/types.h> @@ -67,7 +63,7 @@ static int hppb_probe(struct parisc_device *dev) } card = card->next; } - printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); + printk(KERN_INFO "Found GeckoBoa at 0x%x\n", dev->hpa.start); card->hpa = dev->hpa.start; card->mmio_region.name = "HP-PB Bus"; @@ -78,16 +74,18 @@ static int hppb_probe(struct parisc_device *dev) status = ccio_request_resource(dev, &card->mmio_region); if(status < 0) { - printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08lx, %08lx)\n", + printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08x, %08x)\n", __FILE__, card->mmio_region.start, card->mmio_region.end); } return 0; } - static struct parisc_device_id hppb_tbl[] = { - { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, /* E25 and K */ + { HPHW_BCPORT, 0x0, 0x501, 0xc }, /* E35 */ + { HPHW_BCPORT, 0x0, 0x502, 0xc }, /* E45 */ + { HPHW_BCPORT, 0x0, 0x503, 0xc }, /* E55 */ { 0, } }; diff --git a/drivers/parisc/iosapic_private.h b/drivers/parisc/iosapic_private.h index 41e7ec2..6e05e30 100644 --- a/drivers/parisc/iosapic_private.h +++ b/drivers/parisc/iosapic_private.h @@ -132,7 +132,7 @@ struct iosapic_irt { struct vector_info { struct iosapic_info *iosapic; /* I/O SAPIC this vector is on */ struct irt_entry *irte; /* IRT entry */ - u32 *eoi_addr; /* precalculate EOI reg address */ + u32 __iomem *eoi_addr; /* precalculate EOI reg address */ u32 eoi_data; /* IA64: ? PA: swapped txn_data */ int txn_irq; /* virtual IRQ number for processor */ ulong txn_addr; /* IA64: id_eid PA: partial HPA */ diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index ba67699..21c4c29 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -168,7 +168,8 @@ lba_dump_res(struct resource *r, int d) printk(KERN_DEBUG "(%p)", r->parent); for (i = d; i ; --i) printk(" "); - printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags); + printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, + (long)r->start, (long)r->end, r->flags); lba_dump_res(r->child, d+2); lba_dump_res(r->sibling, d); } @@ -647,7 +648,7 @@ truncate_pat_collision(struct resource *root, struct resource *new) printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] " "to [%lx,%lx]\n", start, end, - new->start, new->end ); + (long)new->start, (long)new->end ); return 0; /* truncation successful */ } @@ -715,8 +716,8 @@ lba_fixup_bus(struct pci_bus *bus) printk("FAILED: lba_fixup_bus() request for " "elmmio_space [%lx/%lx]\n", - ldev->hba.elmmio_space.start, - ldev->hba.elmmio_space.end); + (long)ldev->hba.elmmio_space.start, + (long)ldev->hba.elmmio_space.end); /* lba_dump_res(&iomem_resource, 2); */ /* BUG(); */ @@ -738,15 +739,15 @@ lba_fixup_bus(struct pci_bus *bus) &(ldev->hba.lmmio_space))) { printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n", - ldev->hba.lmmio_space.start, - ldev->hba.lmmio_space.end); + (long)ldev->hba.lmmio_space.start, + (long)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); + (long)ldev->hba.lmmio_space.start, + (long)ldev->hba.lmmio_space.end); } else bus->resource[i++] = &(ldev->hba.lmmio_space); } @@ -758,8 +759,8 @@ lba_fixup_bus(struct pci_bus *bus) if (err < 0) { printk("FAILED: lba_fixup_bus() request for " "gmmio_space [%lx/%lx]\n", - ldev->hba.gmmio_space.start, - ldev->hba.gmmio_space.end); + (long)ldev->hba.gmmio_space.start, + (long)ldev->hba.gmmio_space.end); lba_dump_res(&iomem_resource, 2); BUG(); } @@ -980,7 +981,7 @@ LBA_PORT_IN(32, 0) #define LBA_PORT_OUT(size, mask) \ static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ { \ - void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ + void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \ DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ @@ -1063,16 +1064,16 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) /* used to fix up pre-initialized MEM BARs */ if (!lba_dev->hba.lmmio_space.start) { sprintf(lba_dev->hba.lmmio_name, - "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); lba_dev->hba.lmmio_space_offset = p->start - io->start; r = &lba_dev->hba.lmmio_space; r->name = lba_dev->hba.lmmio_name; } else if (!lba_dev->hba.elmmio_space.start) { sprintf(lba_dev->hba.elmmio_name, - "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.elmmio_space; r->name = lba_dev->hba.elmmio_name; } else { @@ -1089,8 +1090,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_GMMIO: /* MMIO space > 4GB phys addr; for 64-bit BAR */ - sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.gmmio_space; r->name = lba_dev->hba.gmmio_name; r->start = p->start; @@ -1112,8 +1113,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) */ lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.io_space; r->name = lba_dev->hba.io_name; r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); @@ -1166,8 +1167,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** Legacy boxes but it's nice to see in /proc/iomem. */ r = &(lba_dev->hba.lmmio_space); - sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.lmmio_name; #if 1 @@ -1275,8 +1276,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** an existing (but unused portion of) distributed range. */ r = &(lba_dev->hba.elmmio_space); - sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.elmmio_name; #if 1 @@ -1297,8 +1298,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif r = &(lba_dev->hba.io_space); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.io_name; r->flags = IORESOURCE_IO; r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L; @@ -1406,13 +1407,20 @@ lba_hw_init(struct lba_device *d) return 0; } - +/* + * Unfortunately, when firmware numbers busses, it doesn't take into account + * Cardbus bridges. So we have to renumber the busses to suit ourselves. + * Elroy/Mercury don't actually know what bus number they're attached to; + * we use bus 0 to indicate the directly attached bus and any other bus + * number will be taken care of by the PCI-PCI bridge. + */ +static unsigned int lba_next_bus = 0; /* -** Determine if lba should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ + * Determine if lba should claim this chip (return 0) or not (return 1). + * If so, initialize the chip and tell other partners in crime they + * have work to do. + */ static int __init lba_driver_probe(struct parisc_device *dev) { @@ -1440,7 +1448,7 @@ lba_driver_probe(struct parisc_device *dev) } printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n", - version, func_class & 0xf, dev->hpa.start); + version, func_class & 0xf, (long)dev->hpa.start); if (func_class < 2) { printk(KERN_WARNING "Can't support LBA older than " @@ -1470,17 +1478,16 @@ lba_driver_probe(struct parisc_device *dev) */ printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n", IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major, - minor, func_class, dev->hpa.start); + minor, func_class, (long)dev->hpa.start); cfg_ops = &mercury_cfg_ops; } else { - printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start); + printk(KERN_ERR "Unknown LBA found at 0x%lx\n", + (long)dev->hpa.start); return -ENODEV; } - /* - ** Tell I/O SAPIC driver we have a IRQ handler/region. - */ + /* Tell I/O SAPIC driver we have a IRQ handler/region. */ tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't @@ -1529,16 +1536,17 @@ lba_driver_probe(struct parisc_device *dev) lba_legacy_resources(dev, lba_dev); } - /* - ** Tell PCI support another PCI bus was found. - ** Walks PCI bus for us too. - */ + if (lba_dev->hba.bus_num.start < lba_next_bus) + lba_dev->hba.bus_num.start = lba_next_bus; + dev->dev.platform_data = lba_dev; lba_bus = lba_dev->hba.hba_bus = pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, cfg_ops, NULL); - if (lba_bus) + if (lba_bus) { + lba_next_bus = lba_bus->subordinate + 1; pci_bus_add_devices(lba_bus); + } /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 9a731c1..d190c05 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -66,8 +66,8 @@ static char lcd_text_default[32] __read_mostly; static struct workqueue_struct *led_wq; -static void led_work_func(void *); -static DECLARE_WORK(led_task, led_work_func, NULL); +static void led_work_func(struct work_struct *); +static DECLARE_DELAYED_WORK(led_task, led_work_func); #if 0 #define DPRINTK(x) printk x @@ -136,7 +136,7 @@ static int start_task(void) /* Create the work queue and queue the LED task */ led_wq = create_singlethread_workqueue("led_wq"); - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); return 0; } @@ -441,7 +441,7 @@ static __inline__ int led_get_diskio_activity(void) #define LED_UPDATE_INTERVAL (1 + (HZ*19/1000)) -static void led_work_func (void *unused) +static void led_work_func (struct work_struct *unused) { static unsigned long last_jiffies; static unsigned long count_HZ; /* counter in range 0..HZ */ @@ -588,7 +588,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d /* Ensure the work is queued */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return 0; @@ -629,7 +629,7 @@ void __init register_led_regions(void) ** avoid a race condition while writing the CMD/DATA register pair. ** */ -int lcd_print( char *str ) +int lcd_print( const char *str ) { int i; @@ -658,7 +658,7 @@ int lcd_print( char *str ) /* re-queue the work */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return lcd_info.lcd_width; diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 97e9dc0..6dedbde 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -2,7 +2,7 @@ * linux/drivers/parisc/power.c * HP PARISC soft power switch support driver * - * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de> + * Copyright (c) 2001-2007 Helge Deller <deller@gmx.de> * All rights reserved. * * @@ -29,7 +29,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * - * * HINT: * Support of the soft power switch button may be enabled or disabled at * runtime through the "/proc/sys/kernel/power" procfs entry. @@ -38,34 +37,28 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/string.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> +#include <linux/kthread.h> #include <asm/pdc.h> #include <asm/io.h> #include <asm/led.h> -#include <asm/uaccess.h> +#define DRIVER_NAME "powersw" +#define KTHREAD_NAME "kpowerswd" -#ifdef DEBUG -# define DPRINTK(x...) printk(x) -#else -# define DPRINTK(x...) -#endif - - -/* filename in /proc which can be used to enable/disable the power switch */ -#define SYSCTL_FILENAME "sys/kernel/power" +/* how often should the power button be polled ? */ +#define POWERSWITCH_POLL_PER_SEC 2 +/* how long does the power button needs to be down until we react ? */ +#define POWERSWITCH_DOWN_SEC 2 +/* assembly code to access special registers */ +/* taken from PCXL ERS page 82 */ #define DIAG_CODE(code) (0x14000000 + ((code)<<5)) -/* this will go to processor.h or any other place... */ -/* taken from PCXL ERS page 82 */ #define MFCPU_X(rDiagReg, t_ch, t_th, code) \ (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) ) @@ -76,111 +69,95 @@ #define __getDIAG(dr) ( { \ register unsigned long __res asm("r28");\ __asm__ __volatile__ ( \ - ".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \ + ".word %1" : "=&r" (__res) : "i" (MFCPU_T(dr,28) ) \ ); \ __res; \ } ) - -static void deferred_poweroff(void *dummy) -{ - if (kill_cad_pid(SIGINT, 1)) { - /* just in case killing init process failed */ - machine_power_off(); - } -} - -/* - * This function gets called from interrupt context. - * As it's called within an interrupt, it wouldn't sync if we don't - * use schedule_work(). - */ - -static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL); - -static void poweroff(void) -{ - static int powering_off __read_mostly; - - if (powering_off) - return; - - powering_off++; - schedule_work(&poweroff_work); -} - - -/* local time-counter for shutdown */ +/* local shutdown counter */ static int shutdown_timer __read_mostly; /* check, give feedback and start shutdown after one second */ static void process_shutdown(void) { if (shutdown_timer == 0) - DPRINTK(KERN_INFO "Shutdown requested...\n"); + printk(KERN_ALERT KTHREAD_NAME ": Shutdown requested...\n"); shutdown_timer++; /* wait until the button was pressed for 1 second */ - if (shutdown_timer == HZ) { -#if defined (DEBUG) || defined(CONFIG_CHASSIS_LCD_LED) - static char msg[] = "Shutting down..."; -#endif - DPRINTK(KERN_INFO "%s\n", msg); + if (shutdown_timer == (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC)) { + static const char msg[] = "Shutting down..."; + printk(KERN_INFO KTHREAD_NAME ": %s\n", msg); lcd_print(msg); - poweroff(); + + /* send kill signal */ + if (kill_cad_pid(SIGINT, 1)) { + /* just in case killing init process failed */ + if (pm_power_off) + pm_power_off(); + } } } -/* main power switch tasklet struct (scheduled from time.c) */ -DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0); +/* main power switch task struct */ +static struct task_struct *power_task; + +/* filename in /proc which can be used to enable/disable the power switch */ +#define SYSCTL_FILENAME "sys/kernel/power" /* soft power switch enabled/disabled */ int pwrsw_enabled __read_mostly = 1; -/* - * On gecko style machines (e.g. 712/xx and 715/xx) - * the power switch status is stored in Bit 0 ("the highest bit") - * of CPU diagnose register 25. - * - */ -static void gecko_tasklet_func(unsigned long unused) +/* main kernel thread worker. It polls the button state */ +static int kpowerswd(void *param) { - if (unlikely(!pwrsw_enabled)) - return; - - if (__getDIAG(25) & 0x80000000) { - /* power switch button not pressed or released again */ - /* Warning: Some machines do never reset this DIAG flag! */ - shutdown_timer = 0; - } else { - process_shutdown(); - } -} - + __set_current_state(TASK_RUNNING); + + do { + int button_not_pressed; + unsigned long soft_power_reg = (unsigned long) param; + + schedule_timeout_interruptible(pwrsw_enabled ? HZ : HZ/POWERSWITCH_POLL_PER_SEC); + __set_current_state(TASK_RUNNING); + + if (unlikely(!pwrsw_enabled)) + continue; + + if (soft_power_reg) { + /* + * Non-Gecko-style machines: + * Check the power switch status which is read from the + * real I/O location at soft_power_reg. + * Bit 31 ("the lowest bit) is the status of the power switch. + * This bit is "1" if the button is NOT pressed. + */ + button_not_pressed = (gsc_readl(soft_power_reg) & 0x1); + } else { + /* + * On gecko style machines (e.g. 712/xx and 715/xx) + * the power switch status is stored in Bit 0 ("the highest bit") + * of CPU diagnose register 25. + * Warning: Some machines never reset the DIAG flag, even if + * the button has been released again. + */ + button_not_pressed = (__getDIAG(25) & 0x80000000); + } + + if (likely(button_not_pressed)) { + if (unlikely(shutdown_timer && /* avoid writing if not necessary */ + shutdown_timer < (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC))) { + shutdown_timer = 0; + printk(KERN_INFO KTHREAD_NAME ": Shutdown request aborted.\n"); + } + } else + process_shutdown(); + + + } while (!kthread_should_stop()); - -/* - * Check the power switch status which is read from the - * real I/O location at soft_power_reg. - * Bit 31 ("the lowest bit) is the status of the power switch. - */ - -static void polling_tasklet_func(unsigned long soft_power_reg) -{ - unsigned long current_status; - - if (unlikely(!pwrsw_enabled)) - return; - - current_status = gsc_readl(soft_power_reg); - if (current_status & 0x1) { - /* power switch button not pressed */ - shutdown_timer = 0; - } else { - process_shutdown(); - } + return 0; } @@ -220,7 +197,7 @@ static struct notifier_block parisc_panic_block = { static int __init power_init(void) { unsigned long ret; - unsigned long soft_power_reg = 0; + unsigned long soft_power_reg; #if 0 request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt, @@ -235,44 +212,44 @@ static int __init power_init(void) soft_power_reg = -1UL; switch (soft_power_reg) { - case 0: printk(KERN_INFO "Gecko-style soft power switch enabled.\n"); - power_tasklet.func = gecko_tasklet_func; + case 0: printk(KERN_INFO DRIVER_NAME ": Gecko-style soft power switch enabled.\n"); break; - case -1UL: printk(KERN_INFO "Soft power switch support not available.\n"); + case -1UL: printk(KERN_INFO DRIVER_NAME ": Soft power switch support not available.\n"); return -ENODEV; - default: printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n", + default: printk(KERN_INFO DRIVER_NAME ": Soft power switch at 0x%08lx enabled.\n", soft_power_reg); - power_tasklet.data = soft_power_reg; - power_tasklet.func = polling_tasklet_func; + } + + power_task = kthread_run(kpowerswd, (void*)soft_power_reg, KTHREAD_NAME); + if (IS_ERR(power_task)) { + printk(KERN_ERR DRIVER_NAME ": thread creation failed. Driver not loaded.\n"); + pdc_soft_power_button(0); + return -EIO; } /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &parisc_panic_block); - tasklet_enable(&power_tasklet); - return 0; } static void __exit power_exit(void) { - if (!power_tasklet.func) - return; + kthread_stop(power_task); - tasklet_disable(&power_tasklet); atomic_notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); - power_tasklet.func = NULL; + pdc_soft_power_button(0); } -module_init(power_init); +arch_initcall(power_init); module_exit(power_exit); -MODULE_AUTHOR("Helge Deller"); +MODULE_AUTHOR("Helge Deller <deller@gmx.de>"); MODULE_DESCRIPTION("Soft power switch driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 76a29da..322957a 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -109,7 +109,7 @@ static unsigned long piranha_bad_128k = 0; #ifdef SBA_AGP_SUPPORT static int sba_reserve_agpgart = 1; -module_param(sba_reserve_agpgart, int, 1); +module_param(sba_reserve_agpgart, int, 0444); MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); #endif @@ -846,7 +846,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size, if (!hwdev) { /* only support PCI */ *dma_handle = 0; - return 0; + return NULL; } ret = (void *) __get_free_pages(gfp, get_order(size)); diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index ccb8fa1..8321101 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -51,7 +51,11 @@ #define MUX_NR 256 static unsigned int port_cnt __read_mostly; -static struct uart_port mux_ports[MUX_NR]; +struct mux_port { + struct uart_port port; + int enabled; +}; +static struct mux_port mux_ports[MUX_NR]; static struct uart_driver mux_driver = { .owner = THIS_MODULE, @@ -66,7 +70,36 @@ static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) -#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 + +/** + * get_mux_port_count - Get the number of available ports on the Mux. + * @dev: The parisc device. + * + * This function is used to determine the number of ports the Mux + * supports. The IODC data reports the number of ports the Mux + * can support, but there are cases where not all the Mux ports + * are connected. This function can override the IODC and + * return the true port count. + */ +static int __init get_mux_port_count(struct parisc_device *dev) +{ + int status; + u8 iodc_data[32]; + unsigned long bytecnt; + + /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), + * we only need to allocate resources for 1 port since the + * other 7 ports are not connected. + */ + if(dev->id.hversion == 0x15) + return 1; + + status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); + BUG_ON(status != PDC_OK); + + /* Return the number of ports specified in the iodc data. */ + return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; +} /** * mux_tx_empty - Check if the transmitter fifo is empty. @@ -250,7 +283,7 @@ static void mux_read(struct uart_port *port) */ static int mux_startup(struct uart_port *port) { - mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + mux_ports[port->line].enabled = 1; return 0; } @@ -262,6 +295,7 @@ static int mux_startup(struct uart_port *port) */ static void mux_shutdown(struct uart_port *port) { + mux_ports[port->line].enabled = 0; } /** @@ -319,7 +353,7 @@ static int mux_request_port(struct uart_port *port) * @port: Ptr to the uart_port. * @type: Bitmask of required configurations. * - * Perform any autoconfiguration steps for the port. This functino is + * Perform any autoconfiguration steps for the port. This function is * called if the UPF_BOOT_AUTOCONF flag is specified for the port. * [Note: This is required for now because of a bug in the Serial core. * rmk has already submitted a patch to linus, should be available for @@ -357,11 +391,11 @@ static void mux_poll(unsigned long unused) int i; for(i = 0; i < port_cnt; ++i) { - if(!mux_ports[i].info) + if(!mux_ports[i].enabled) continue; - mux_read(&mux_ports[i]); - mux_write(&mux_ports[i]); + mux_read(&mux_ports[i].port); + mux_write(&mux_ports[i].port); } mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); @@ -371,8 +405,17 @@ static void mux_poll(unsigned long unused) #ifdef CONFIG_SERIAL_MUX_CONSOLE static void mux_console_write(struct console *co, const char *s, unsigned count) { - while(count--) - pdc_iodc_putc(*s++); + /* Wait until the FIFO drains. */ + while(UART_GET_FIFO_CNT(&mux_ports[0].port)) + udelay(1); + + while(count--) { + if(*s == '\n') { + UART_PUT_CHAR(&mux_ports[0].port, '\r'); + } + UART_PUT_CHAR(&mux_ports[0].port, *s++); + } + } static int mux_console_setup(struct console *co, char *options) @@ -428,19 +471,14 @@ static struct uart_ops mux_pops = { */ static int __init mux_probe(struct parisc_device *dev) { - int i, status, ports; - u8 iodc_data[32]; - unsigned long bytecnt; - struct uart_port *port; + int i, status; - status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); - if(status != PDC_OK) { - printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); - return 1; - } + int port_count = get_mux_port_count(dev); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); - ports = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports); + dev_set_drvdata(&dev->dev, (void *)(long)port_count); + request_mem_region(dev->hpa.start + MUX_OFFSET, + port_count * MUX_LINE_OFFSET, "Mux"); if(!port_cnt) { mux_driver.cons = MUX_CONSOLE; @@ -450,13 +488,10 @@ static int __init mux_probe(struct parisc_device *dev) printk(KERN_ERR "Serial mux: Unable to register driver.\n"); return 1; } - - init_timer(&mux_timer); - mux_timer.function = mux_poll; } - for(i = 0; i < ports; ++i, ++port_cnt) { - port = &mux_ports[port_cnt]; + for(i = 0; i < port_count; ++i, ++port_cnt) { + struct uart_port *port = &mux_ports[port_cnt].port; port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); @@ -477,27 +512,73 @@ static int __init mux_probe(struct parisc_device *dev) */ port->timeout = HZ / 50; spin_lock_init(&port->lock); + status = uart_add_one_port(&mux_driver, port); BUG_ON(status); } -#ifdef CONFIG_SERIAL_MUX_CONSOLE - register_console(&mux_console); -#endif return 0; } +static int __devexit mux_remove(struct parisc_device *dev) +{ + int i, j; + int port_count = (long)dev_get_drvdata(&dev->dev); + + /* Find Port 0 for this card in the mux_ports list. */ + for(i = 0; i < port_cnt; ++i) { + if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) + break; + } + BUG_ON(i + port_count > port_cnt); + + /* Release the resources associated with each port on the device. */ + for(j = 0; j < port_count; ++j, ++i) { + struct uart_port *port = &mux_ports[i].port; + + uart_remove_one_port(&mux_driver, port); + if(port->membase) + iounmap(port->membase); + } + + release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); + return 0; +} + +/* Hack. This idea was taken from the 8250_gsc.c on how to properly order + * the serial port detection in the proper order. The idea is we always + * want the builtin mux to be detected before addin mux cards, so we + * specifically probe for the builtin mux cards first. + * + * This table only contains the parisc_device_id of known builtin mux + * devices. All other mux cards will be detected by the generic mux_tbl. + */ +static struct parisc_device_id builtin_mux_tbl[] = { + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ + { 0, } +}; + static struct parisc_device_id mux_tbl[] = { { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); MODULE_DEVICE_TABLE(parisc, mux_tbl); +static struct parisc_driver builtin_serial_mux_driver = { + .name = "builtin_serial_mux", + .id_table = builtin_mux_tbl, + .probe = mux_probe, + .remove = __devexit_p(mux_remove), +}; + static struct parisc_driver serial_mux_driver = { .name = "serial_mux", .id_table = mux_tbl, .probe = mux_probe, + .remove = __devexit_p(mux_remove), }; /** @@ -507,7 +588,21 @@ static struct parisc_driver serial_mux_driver = { */ static int __init mux_init(void) { - return register_parisc_driver(&serial_mux_driver); + register_parisc_driver(&builtin_serial_mux_driver); + register_parisc_driver(&serial_mux_driver); + + if(port_cnt > 0) { + /* Start the Mux timer */ + init_timer(&mux_timer); + mux_timer.function = mux_poll; + mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + +#ifdef CONFIG_SERIAL_MUX_CONSOLE + register_console(&mux_console); +#endif + } + + return 0; } /** @@ -517,14 +612,16 @@ static int __init mux_init(void) */ static void __exit mux_exit(void) { - int i; - - for (i = 0; i < port_cnt; i++) { - uart_remove_one_port(&mux_driver, &mux_ports[i]); - if (mux_ports[i].membase) - iounmap(mux_ports[i].membase); + /* Delete the Mux timer. */ + if(port_cnt > 0) { + del_timer(&mux_timer); +#ifdef CONFIG_SERIAL_MUX_CONSOLE + unregister_console(&mux_console); +#endif } + unregister_parisc_driver(&builtin_serial_mux_driver); + unregister_parisc_driver(&serial_mux_driver); uart_unregister_driver(&mux_driver); } |