Merge branch 'for_2.6.29' of git://git.kernel.org/pub/scm/linux/kernel/git/kkeil...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 12 Jan 2009 23:57:34 +0000 (15:57 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 12 Jan 2009 23:57:34 +0000 (15:57 -0800)
* 'for_2.6.29' of git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6:
  Fix small typo
  misdn: indentation and braces disagree - add braces
  misdn: one handmade ARRAY_SIZE converted
  drivers/isdn/hardware/mISDN: move a dereference below a NULL test
  indentation & braces disagree - add braces
  Make parameter debug writable
  BUGFIX: used NULL pointer at ioctl(sk,IMGETDEVINFO,&devinfo) when devinfo.id not registered

89 files changed:
arch/m68k/amiga/amiints.c
arch/m68k/amiga/cia.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/stdma.c
arch/m68k/atari/time.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/time.c
arch/m68k/kernel/.gitignore [new file with mode: 0644]
arch/m68k/kernel/entry.S
arch/m68k/kernel/setup.c
arch/m68k/kernel/signal.c
arch/m68k/kernel/vmlinux-sun3.lds
arch/m68k/mac/baboon.c
arch/m68k/mac/config.c
arch/m68k/mac/debug.c
arch/m68k/mac/iop.c
arch/m68k/mac/macints.c
arch/m68k/mac/misc.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/math-emu/fp_log.c
arch/m68k/mm/init.c
arch/m68k/mm/motorola.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/config.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/sun3ints.c
arch/m68k/sun3x/config.c
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/x86/include/asm/mach-default/mach_wakecpu.h
arch/x86/include/asm/mtrr.h
arch/x86/kernel/apic.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/mpparse.c
arch/x86/mm/fault.c
drivers/block/amiflop.c
drivers/char/amiserial.c
drivers/char/ser_a2232.c
drivers/char/vme_scc.c
drivers/dio/dio-sysfs.c
drivers/dio/dio.c
drivers/video/Makefile
drivers/video/amifb.c
drivers/video/atafb.c
drivers/video/c2p.c [deleted file]
drivers/video/c2p.h
drivers/video/c2p_core.h [new file with mode: 0644]
drivers/video/c2p_iplan2.c [new file with mode: 0644]
drivers/video/c2p_planar.c [new file with mode: 0644]
drivers/video/console/fbcon.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/gef_wdt.c [new file with mode: 0644]
drivers/watchdog/pika_wdt.c [new file with mode: 0644]
drivers/watchdog/wm8350_wdt.c
drivers/zorro/.gitignore [new file with mode: 0644]
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
drivers/zorro/zorro.h
fs/dlm/debug_fs.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/recover.c
include/asm-m68k/unistd.h
include/linux/dio.h
include/sound/soc-dapm.h
include/sound/soc.h
sound/oss/dmasound/dmasound_atari.c
sound/oss/dmasound/dmasound_q40.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_nvhdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/twl4030.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/usb/caiaq/caiaq-device.c
sound/usb/caiaq/caiaq-device.h
sound/usb/caiaq/caiaq-midi.c

index 907a5533c845792e74fb9365378a527f45eb8b8a..c5b5212cc3f91544f42b27f73323f9cf0a9bfc42 100644 (file)
@@ -72,10 +72,14 @@ static struct irq_controller amiga_irq_controller = {
 
 void __init amiga_init_IRQ(void)
 {
-       request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
-       request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
-       request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
-       request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
+       if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
+               pr_err("Couldn't register int%d\n", 1);
+       if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
+               pr_err("Couldn't register int%d\n", 3);
+       if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
+               pr_err("Couldn't register int%d\n", 4);
+       if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
+               pr_err("Couldn't register int%d\n", 5);
 
        m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
 
index 343fab49bd9a751435ae710bd4e848c9b6abd6ec..ecd0f7ca6f0e34caca534e4dcc3a445805649741 100644 (file)
@@ -176,5 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base)
        /* override auto int and install CIA handler */
        m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
        m68k_irq_startup(base->handler_irq);
-       request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base);
+       if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
+                       base->name, base))
+               pr_err("Couldn't register %s interrupt\n", base->name);
 }
index ab9862c3a136f4bc49f744b04bd2feae51912e83..6e562751ad51b5653181165d8b4ffc54f6cb1b8b 100644 (file)
@@ -493,7 +493,8 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
         * Please don't change this to use ciaa, as it interferes with the
         * SCSI code. We'll have to take a look at this later
         */
-       request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
+       if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
+               pr_err("Couldn't register timer interrupt\n");
        /* start timer */
        ciab.cra |= 0x11;
 }
index 78df98f2029af9e5556f33973c71949da070a8fc..8d3eafab1ffeb0f89aae3a64697aa47827a7b11b 100644 (file)
@@ -31,10 +31,6 @@ extern unsigned long dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern int dn_dummy_set_clock_mmss(unsigned long);
 extern void dn_dummy_reset(void);
-extern void dn_dummy_waitbut(void);
-extern struct fb_info *dn_fb_init(long *);
-extern void dn_dummy_debug_init(void);
-extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
 #ifdef CONFIG_HEARTBEAT
 static void dn_heartbeat(int on);
 #endif
@@ -204,7 +200,8 @@ void dn_sched_init(irq_handler_t timer_routine)
        printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
 #endif
 
-       request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
+       if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
+               pr_err("Couldn't register timer interrupt\n");
 }
 
 unsigned long dn_gettimeoffset(void) {
index c038b7c7eff0e8ea20f009b83eb4b1658040a229..a5f33c059979077ea17229a97c36fe692041cb23 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/atari_joystick.h>
 #include <asm/irq.h>
 
-extern unsigned int keymap_count;
 
 /* Hook for MIDI serial driver */
 void (*atari_MIDI_interrupt_hook) (void);
@@ -567,14 +566,19 @@ static int atari_keyb_done = 0;
 
 int atari_keyb_init(void)
 {
+       int error;
+
        if (atari_keyb_done)
                return 0;
 
        kb_state.state = KEYBOARD;
        kb_state.len = 0;
 
-       request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
-                   "keyboard/mouse/MIDI", atari_keyboard_interrupt);
+       error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
+                           IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
+                           atari_keyboard_interrupt);
+       if (error)
+               return error;
 
        atari_turnoff_irq(IRQ_MFP_ACIA);
        do {
index d1bd029a34ac612acfe5b04936a8dab1821ce2de..604329fafbb86d2bd4219a06b6c5a384bc0225e8 100644 (file)
@@ -179,8 +179,9 @@ EXPORT_SYMBOL(stdma_islocked);
 void __init stdma_init(void)
 {
        stdma_isr = NULL;
-       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
-                   "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
+       if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
+                       "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
+               pr_err("Couldn't register ST-DMA interrupt\n");
 }
 
 
index 1edde27fa32dbb600dd5d07822cfd0bb5281b992..d076ff8d1b39138ba16b4483d2874a7d5b4bcaa9 100644 (file)
@@ -31,8 +31,9 @@ atari_sched_init(irq_handler_t timer_routine)
     /* start timer C, div = 1:100 */
     mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
-    request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
-                "timer", timer_routine);
+    if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
+                   "timer", timer_routine))
+       pr_err("Couldn't register timer interrupt\n");
 }
 
 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
index c072595928c06d0496df7ec0b9a197b763709925..9fe6fefb5e142f5c238441d885fe6ddc076fe19e 100644 (file)
@@ -43,7 +43,6 @@ extern unsigned long bvme6000_gettimeoffset (void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
 extern void bvme6000_reset (void);
-extern void bvme6000_waitbut(void);
 void bvme6000_set_vectors (void);
 
 /* Save tick handler routine pointer, will point to do_timer() in
index dd7c8a2583d3395eaa877580905c821f9556e3c6..f6312c7d87276a1c2e4b23005874a0b247689c8a 100644 (file)
@@ -70,7 +70,8 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+    pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);              /* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x40);             /* enable irq */
diff --git a/arch/m68k/kernel/.gitignore b/arch/m68k/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index f28404d9a2bc3594438904f9b23bf97112534b63..5b780826647cce7e90bedfc8243c302c91ffaa71 100644 (file)
@@ -424,7 +424,7 @@ resume:
 .data
 ALIGN
 sys_call_table:
-       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
        .long sys_exit
        .long sys_fork
        .long sys_read
index 4d97bd2bd573845db42d11b8b03c096b5148eac9..303730afb1c9d5ef0163c7640fee6bc3c057bdc1 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/initrd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
 #include <asm/irq.h>
@@ -62,7 +63,6 @@ EXPORT_SYMBOL(vme_brdtype);
 int m68k_is040or060;
 EXPORT_SYMBOL(m68k_is040or060);
 
-extern int end;
 extern unsigned long availmem;
 
 int m68k_num_memory;
@@ -215,11 +215,10 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
 void __init setup_arch(char **cmdline_p)
 {
-       extern int _etext, _edata, _end;
        int i;
 
        /* The bootinfo is located right after the kernel bss */
-       m68k_parse_bootinfo((const struct bi_record *)&_end);
+       m68k_parse_bootinfo((const struct bi_record *)_end);
 
        if (CPU_IS_040)
                m68k_is040or060 = 4;
@@ -252,9 +251,9 @@ void __init setup_arch(char **cmdline_p)
        }
 
        init_mm.start_code = PAGE_OFFSET;
-       init_mm.end_code = (unsigned long) &_etext;
-       init_mm.end_data = (unsigned long) &_edata;
-       init_mm.brk = (unsigned long) &_end;
+       init_mm.end_code = (unsigned long)_etext;
+       init_mm.end_data = (unsigned long)_edata;
+       init_mm.brk = (unsigned long)_end;
 
        *cmdline_p = m68k_command_line;
        memcpy(boot_command_line, *cmdline_p, CL_SIZE);
index f9af893cd2892dde83b6e089d370d093f6db2ac0..de2d05ddd86d9d8ca6c7699f3d93d9ca0ad05861 100644 (file)
@@ -326,6 +326,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
        struct sigcontext context;
        int err;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        /* get previous context */
        if (copy_from_user(&context, usc, sizeof(context)))
                goto badframe;
@@ -411,6 +414,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
        unsigned long usp;
        int err;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        err = __get_user(temp, &uc->uc_mcontext.version);
        if (temp != MCONTEXT_VERSION)
                goto badframe;
@@ -937,6 +943,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
                regs->d0 = -EINTR;
                break;
 
+       case -ERESTART_RESTARTBLOCK:
+               if (!has_handler) {
+                       regs->d0 = __NR_restart_syscall;
+                       regs->pc -= 2;
+                       break;
+               }
+               regs->d0 = -EINTR;
+               break;
+
        case -ERESTARTSYS:
                if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
                        regs->d0 = -EINTR;
index 8a4919e4d36a4ef23c996b4a3f4a4dc51d4ddb1e..d9368c0709ba7fc913ffb27377d41ebe53cd2b97 100644 (file)
@@ -33,6 +33,7 @@ SECTIONS
        } :data
   /* End of data goes *here* so that freeing init code works properly. */
   _edata = .;
+  NOTES
 
   /* will be freed after init */
   . = ALIGN(PAGE_SIZE);        /* Init code and data */
index 245d16d078ad817c93bacf94fc15f72803e8e337..2a96bebd8969eb6ef304a00c8f833e010465881c 100644 (file)
@@ -92,7 +92,8 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
 void __init baboon_register_interrupts(void)
 {
        baboon_disabled = 0;
-       request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon);
+       if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
+               pr_err("Couldn't register baboon interrupt\n");
 }
 
 /*
index 8819b97be32401b096587de6dcdda41e504a1749..98b6bcfb37bf4c10aa7e073c899ef84b0e0d4854 100644 (file)
 
 struct mac_booter_data mac_bi_data;
 
-/* New m68k bootinfo stuff and videobase */
-
-extern int m68k_num_memory;
-extern struct mem_info m68k_memory[NUM_MEMINFO];
-
-extern struct mem_info m68k_ramdisk;
-
 /* The phys. video addr. - might be bogus on some machines */
 static unsigned long mac_orig_videoaddr;
 
@@ -61,7 +54,6 @@ static unsigned long mac_orig_videoaddr;
 extern unsigned long mac_gettimeoffset(void);
 extern int mac_hwclk(int, struct rtc_time *);
 extern int mac_set_clock_mmss(unsigned long);
-extern int show_mac_interrupts(struct seq_file *, void *);
 extern void iop_preinit(void);
 extern void iop_init(void);
 extern void via_init(void);
@@ -805,10 +797,6 @@ static void __init mac_identify(void)
                mac_bi_data.boottime, mac_bi_data.gmtbias);
        printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
                mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
-#if 0
-       printk("Ramdisk: addr 0x%lx size 0x%lx\n",
-               m68k_ramdisk.addr, m68k_ramdisk.size);
-#endif
 
        iop_init();
        via_init();
index 65dd77a742a341c493a64982b16a0ec5de60d445..bce074ceb768d9adf97e13c783263a719a9c1677 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/macints.h>
 
 extern unsigned long mac_videobase;
-extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
 
 extern void mac_serial_print(const char *);
index 326fb9978094961221c14ce4a53a596ee3934816..1ad4e9d80eba7f5be93f530c262636136a01b5b8 100644 (file)
@@ -305,14 +305,16 @@ void __init iop_register_interrupts(void)
 {
        if (iop_ism_present) {
                if (oss_present) {
-                       request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
                                        IRQ_FLG_LOCK, "ISM IOP",
-                                       (void *) IOP_NUM_ISM);
+                                       (void *) IOP_NUM_ISM))
+                               pr_err("Couldn't register ISM IOP interrupt\n");
                        oss_irq_enable(IRQ_MAC_ADB);
                } else {
-                       request_irq(IRQ_VIA2_0, iop_ism_irq,
+                       if (request_irq(IRQ_VIA2_0, iop_ism_irq,
                                        IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-                                       (void *) IOP_NUM_ISM);
+                                       (void *) IOP_NUM_ISM))
+                               pr_err("Couldn't register ISM IOP interrupt\n");
                }
                if (!iop_alive(iop_base[IOP_NUM_ISM])) {
                        printk("IOP: oh my god, they killed the ISM IOP!\n");
index 82e560c076ce31e1cf82968ac3622f7c58c9a135..23711074e0e2d7ce12342a4e89436a74bf0f77ff 100644 (file)
 #include <asm/errno.h>
 #include <asm/macints.h>
 #include <asm/irq_regs.h>
+#include <asm/mac_oss.h>
 
 #define DEBUG_SPURIOUS
 #define SHUTUP_SONIC
@@ -146,7 +147,6 @@ static int scc_mask;
  * VIA/RBV hooks
  */
 
-extern void via_init(void);
 extern void via_register_interrupts(void);
 extern void via_irq_enable(int);
 extern void via_irq_disable(int);
@@ -157,9 +157,6 @@ extern int  via_irq_pending(int);
  * OSS hooks
  */
 
-extern int oss_present;
-
-extern void oss_init(void);
 extern void oss_register_interrupts(void);
 extern void oss_irq_enable(int);
 extern void oss_irq_disable(int);
@@ -170,9 +167,6 @@ extern int  oss_irq_pending(int);
  * PSC hooks
  */
 
-extern int psc_present;
-
-extern void psc_init(void);
 extern void psc_register_interrupts(void);
 extern void psc_irq_enable(int);
 extern void psc_irq_disable(int);
@@ -191,12 +185,10 @@ extern void iop_register_interrupts(void);
 
 extern int baboon_present;
 
-extern void baboon_init(void);
 extern void baboon_register_interrupts(void);
 extern void baboon_irq_enable(int);
 extern void baboon_irq_disable(int);
 extern void baboon_irq_clear(int);
-extern int  baboon_irq_pending(int);
 
 /*
  * SCC interrupt routines
@@ -258,8 +250,9 @@ void __init mac_init_IRQ(void)
        if (baboon_present)
                baboon_register_interrupts();
        iop_register_interrupts();
-       request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
-                       mac_nmi_handler);
+       if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
+                       mac_nmi_handler))
+               pr_err("Couldn't register NMI\n");
 #ifdef DEBUG_MACINTS
        printk("mac_init_IRQ(): Done!\n");
 #endif
index a44c7086ab39a3b9352f2b3c5f0202b9e57bd471..5d818568b343719a7ab82f9a8fb075a048a9535e 100644 (file)
@@ -35,7 +35,6 @@
 
 #define RTC_OFFSET 2082844800
 
-extern struct mac_booter_data mac_bi_data;
 static void (*rom_reset)(void);
 
 #ifdef CONFIG_ADB_CUDA
index 8426501119ca82bf641b3098c4a726d696cc26bb..f3d23d6ebcf8a7ba35e7b07e70e0d4b7276f6ebb 100644 (file)
@@ -66,16 +66,21 @@ void __init oss_init(void)
 
 void __init oss_register_interrupts(void)
 {
-       request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-                       "scsi", (void *) oss);
-       request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
-                       "scc", mac_scc_dispatch);
-       request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-                       "nubus", (void *) oss);
-       request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-                       "sound", (void *) oss);
-       request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-                       "via1", (void *) via1);
+       if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+                       "scsi", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "scsi");
+       if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+                       "scc", mac_scc_dispatch))
+               pr_err("Couldn't register %s interrupt\n", "scc");
+       if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+                       "nubus", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "nubus");
+       if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+                       "sound", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "sound");
+       if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+                       "via1", (void *) via1))
+               pr_err("Couldn't register %s interrupt\n", "via1");
 }
 
 /*
index f84a4dd64f94be9788bbea2affed886ef4e78b3f..ba6ccab64018fb9badeafd7b8bbacb51518a5613 100644 (file)
@@ -117,10 +117,14 @@ void __init psc_init(void)
 
 void __init psc_register_interrupts(void)
 {
-       request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
-       request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
-       request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
-       request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
+       if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
+               pr_err("Couldn't register psc%d interrupt\n", 3);
+       if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
+               pr_err("Couldn't register psc%d interrupt\n", 4);
+       if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
+               pr_err("Couldn't register psc%d interrupt\n", 5);
+       if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
+               pr_err("Couldn't register psc%d interrupt\n", 6);
 }
 
 /*
index f01d418e64fed5c1fa6c67f9566577d774ec2785..7d97ba54536e6997a5143942737653f8188ee361 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/macints.h>
 #include <asm/mac_via.h>
 #include <asm/mac_psc.h>
+#include <asm/mac_oss.h>
 
 volatile __u8 *via1, *via2;
 int rbv_present;
@@ -84,7 +85,6 @@ void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
 extern irqreturn_t mac_scc_dispatch(int, void *);
-extern int oss_present;
 
 /*
  * Initialize the VIAs
@@ -283,7 +283,8 @@ void __init via_init_clock(irq_handler_t func)
        via1[vT1CL] = MAC_CLOCK_LOW;
        via1[vT1CH] = MAC_CLOCK_HIGH;
 
-       request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
+       if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+               pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
 /*
@@ -293,25 +294,31 @@ void __init via_init_clock(irq_handler_t func)
 void __init via_register_interrupts(void)
 {
        if (via_alt_mapping) {
-               request_irq(IRQ_AUTO_1, via1_irq,
+               if (request_irq(IRQ_AUTO_1, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-                               (void *) via1);
-               request_irq(IRQ_AUTO_6, via1_irq,
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "software");
+               if (request_irq(IRQ_AUTO_6, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1);
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "via1");
        } else {
-               request_irq(IRQ_AUTO_1, via1_irq,
+               if (request_irq(IRQ_AUTO_1, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1);
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "via1");
        }
-       request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "via2", (void *) via2);
+       if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+                       "via2", (void *) via2))
+               pr_err("Couldn't register %s interrupt\n", "via2");
        if (!psc_present) {
-               request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
-                               "scc", mac_scc_dispatch);
+               if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+                               "scc", mac_scc_dispatch))
+                       pr_err("Couldn't register %s interrupt\n", "scc");
        }
-       request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "nubus", (void *) via2);
+       if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
+                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
+               pr_err("Couldn't register %s interrupt\n", "nubus");
 }
 
 /*
index b1033ae0d6f084a357ddf318a8e67b10d789098a..367ecee2f981db6a5763ed4ac69452f20afbd79d 100644 (file)
@@ -24,7 +24,6 @@ static const struct fp_ext fp_one =
 
 extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
 extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
-extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src);
 
 struct fp_ext *
 fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
index 81bb08ceec18372e16110a86fe38b7ca441ba383..0007b2adf3a3ebb85e1d1375f824f638e5c09ee0 100644 (file)
@@ -28,6 +28,7 @@
 #ifdef CONFIG_ATARI
 #include <asm/atari_stram.h>
 #endif
+#include <asm/sections.h>
 #include <asm/tlb.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -73,9 +74,6 @@ extern void init_pointer_table(unsigned long ptable);
 
 /* References to section boundaries */
 
-extern char _text[], _etext[];
-extern char __init_begin[], __init_end[];
-
 extern pmd_t *zero_pgtable;
 
 void __init mem_init(void)
index c5dbb9bdb32283c7978736a3b695907e1c076615..4665fc84b7dcc50ab43174bcf7760f43a5859533 100644 (file)
@@ -30,6 +30,7 @@
 #ifdef CONFIG_ATARI
 #include <asm/atari_stram.h>
 #endif
+#include <asm/sections.h>
 
 #undef DEBUG
 
@@ -301,14 +302,12 @@ void __init paging_init(void)
        }
 }
 
-extern char __init_begin, __init_end;
-
 void free_initmem(void)
 {
        unsigned long addr;
 
-       addr = (unsigned long)&__init_begin;
-       for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
+       addr = (unsigned long)__init_begin;
+       for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
                virt_to_page(addr)->flags &= ~(1 << PG_reserved);
                init_page_count(virt_to_page(addr));
                free_page(addr);
index 43cdf476ffab17cd690b1bb8e8abba98082755a4..100baaa692a14fecc4d1cf74c995d3b43f210e1c 100644 (file)
@@ -42,7 +42,6 @@ extern unsigned long mvme147_gettimeoffset (void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
 extern void mvme147_reset (void);
-extern void mvme147_waitbut(void);
 
 
 static int bcd2int (unsigned char b);
@@ -115,8 +114,9 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
        tick_handler = timer_routine;
-       request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
-               IRQ_FLG_REPLACE, "timer 1", NULL);
+       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
+                       "timer 1", NULL))
+               pr_err("Couldn't register timer interrupt\n");
 
        /* Init the clock with a value */
        /* our clock goes off every 6.25us */
index 1521826fc3c7caef9a62935a2bde21f0f6135378..11edf61cc2c4cb864b5a092bf9e1b2ba018f15ee 100644 (file)
@@ -48,7 +48,6 @@ extern unsigned long mvme16x_gettimeoffset (void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
 extern void mvme16x_reset (void);
-extern void mvme16x_waitbut(void);
 
 int bcd2int (unsigned char b);
 
index 7110546e3c00f412dcc88c7ad69111feb890d339..31ab3f08bbda25ad37be9a26abeb3f511c25b554 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/machdep.h>
 #include <asm/q40_master.h>
 
-extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
 extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 extern void q40_sched_init(irq_handler_t handler);
@@ -47,8 +46,6 @@ static unsigned int q40_get_ss(void);
 static int q40_set_clock_mmss(unsigned long);
 static int q40_get_rtc_pll(struct rtc_pll_info *pll);
 static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_waitbut(void);
-void q40_set_vectors(void);
 
 extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
 
index 8dfaa201342e142726fc7d4671649da57148040a..2ca25bd01a961c37bbdd8a6b12efbf330e252f79 100644 (file)
 #include <asm/sun3mmu.h>
 #include <asm/rtc.h>
 #include <asm/machdep.h>
+#include <asm/idprom.h>
 #include <asm/intersil.h>
 #include <asm/irq.h>
+#include <asm/sections.h>
 #include <asm/segment.h>
 #include <asm/sun3ints.h>
 
-extern char _text, _end;
-
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
 extern unsigned long sun3_gettimeoffset(void);
 static void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
-extern void idprom_init (void);
 extern int sun3_hwclk(int set, struct rtc_time *t);
 
 volatile char* clock_va;
-extern volatile unsigned char* sun3_intreg;
 extern unsigned long availmem;
 unsigned long num_pages;
 
@@ -149,7 +147,7 @@ void __init config_sun3(void)
        mach_halt            =  sun3_halt;
        mach_get_hardware_list = sun3_get_hardware_list;
 
-       memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
+       memory_start = ((((unsigned long)_end) + 0x2000) & ~0x1fff);
 // PROM seems to want the last couple of physical pages. --m
        memory_end   = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
 
index 60f9d4500d729e6d6422240879940414e555303a..3cd19390aae51fcfa73ebe35b8c8075249cf780e 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/mmu_context.h>
 #include <asm/dvma.h>
 
-extern void prom_reboot (char *) __attribute__ ((__noreturn__));
 
 #undef DEBUG_MMU_EMU
 #define DEBUG_PROM_MAPS
index 7364cd67455e94ba410d3aa4b245b62d8abdba1a..ad90393a336101e003a61dedcbc447350fe9aed2 100644 (file)
@@ -105,7 +105,10 @@ void __init sun3_init_IRQ(void)
        m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
        m68k_setup_user_interrupt(VEC_USER, 128, NULL);
 
-       request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
-       request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
-       request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
+       if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
+               pr_err("Couldn't register %s interrupt\n", "int5");
+       if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
+               pr_err("Couldn't register %s interrupt\n", "int7");
+       if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
+               pr_err("Couldn't register %s interrupt\n", "vec255");
 }
index 2b1ca2db070fc429e25cfb9ae9140c5b26f8cbe9..fc599fad4a546542a9ce0a05f9bfe2fe7baa7160 100644 (file)
@@ -23,7 +23,6 @@
 #include "time.h"
 
 volatile char *clock_va;
-extern volatile unsigned char *sun3_intreg;
 
 extern void sun3_get_model(char *model);
 
index 9708b3423bbdc11615a481f572af7792e38d0bbe..e78c355c7bac8974ea2c84e55856499b260bbbc7 100644 (file)
                        compatible = "gef,fpga-regs";
                        reg = <0x4 0x0 0x40>;
                };
+
+               wdt@4,2000 {
+                       compatible = "gef,fpga-wdt";
+                       reg = <0x4 0x2000 0x8>;
+                       interrupts = <0x1a 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               /* Second watchdog available, driver currently supports one.
+               wdt@4,2010 {
+                       compatible = "gef,fpga-wdt";
+                       reg = <0x4 0x2010 0x8>;
+                       interrupts = <0x1b 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               */
                gef_pic: pic@4,4000 {
                        #interrupt-cells = <1>;
                        interrupt-controller;
index cd1ffa44932779daa077f8cd229243f3ad8e2a3d..391874c7b43643d04f2cc38e351eec77e315e04c 100644 (file)
@@ -1164,6 +1164,7 @@ CONFIG_WATCHDOG=y
 # CONFIG_SOFT_WATCHDOG is not set
 # CONFIG_ALIM7101_WDT is not set
 # CONFIG_8xxx_WDT is not set
+CONFIG_GEF_WDT=y
 
 #
 # PCI-based Watchdog Cards
index ceb01366014629ba1c8220dff2a95bb313a2bf30..89897a6a65b92cef3aa1ca273f0142fda877c3e7 100644 (file)
@@ -24,7 +24,13 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
 {
 }
 
+#ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
+#else /* CONFIG_SMP */
+static inline void __inquire_remote_apic(int apicid)
+{
+}
+#endif /* CONFIG_SMP */
 
 static inline void inquire_remote_apic(int apicid)
 {
index cb988aab716dfc7c30467ae32adce09dbb7489e6..14080d22edb30221300547c855923089c80b8678 100644 (file)
@@ -58,15 +58,15 @@ struct mtrr_gentry {
 #endif /* !__i386__ */
 
 struct mtrr_var_range {
-       u32 base_lo;
-       u32 base_hi;
-       u32 mask_lo;
-       u32 mask_hi;
+       __u32 base_lo;
+       __u32 base_hi;
+       __u32 mask_lo;
+       __u32 mask_hi;
 };
 
 /* In the Intel processor's MTRR interface, the MTRR type is always held in
    an 8 bit field: */
-typedef u8 mtrr_type;
+typedef __u8 mtrr_type;
 
 #define MTRR_NUM_FIXED_RANGES 88
 #define MTRR_MAX_VAR_RANGES 256
index 566a08466b191dd2ac2097b3df676bd072d1ccdf..0f830e4f56751d0d8499ac64d549b72ee12203a2 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/proto.h>
 #include <asm/apic.h>
 #include <asm/i8259.h>
+#include <asm/smp.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
index 06fcd8f9323cccda93a40f0dfc87cce1c9ea68c7..6f11e029e8c58a9e1ba12d404c3aac0a90f55606 100644 (file)
@@ -150,9 +150,8 @@ struct drv_cmd {
        u32 val;
 };
 
-static long do_drv_read(void *_cmd)
+static void do_drv_read(struct drv_cmd *cmd)
 {
-       struct drv_cmd *cmd = _cmd;
        u32 h;
 
        switch (cmd->type) {
@@ -167,12 +166,10 @@ static long do_drv_read(void *_cmd)
        default:
                break;
        }
-       return 0;
 }
 
-static long do_drv_write(void *_cmd)
+static void do_drv_write(struct drv_cmd *cmd)
 {
-       struct drv_cmd *cmd = _cmd;
        u32 lo, hi;
 
        switch (cmd->type) {
@@ -189,23 +186,30 @@ static long do_drv_write(void *_cmd)
        default:
                break;
        }
-       return 0;
 }
 
 static void drv_read(struct drv_cmd *cmd)
 {
+       cpumask_t saved_mask = current->cpus_allowed;
        cmd->val = 0;
 
-       work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd);
+       set_cpus_allowed_ptr(current, cmd->mask);
+       do_drv_read(cmd);
+       set_cpus_allowed_ptr(current, &saved_mask);
 }
 
 static void drv_write(struct drv_cmd *cmd)
 {
+       cpumask_t saved_mask = current->cpus_allowed;
        unsigned int i;
 
        for_each_cpu(i, cmd->mask) {
-               work_on_cpu(i, do_drv_write, cmd);
+               set_cpus_allowed_ptr(current, cpumask_of(i));
+               do_drv_write(cmd);
        }
+
+       set_cpus_allowed_ptr(current, &saved_mask);
+       return;
 }
 
 static u32 get_cur_val(const struct cpumask *mask)
@@ -231,15 +235,10 @@ static u32 get_cur_val(const struct cpumask *mask)
                return 0;
        }
 
-       if (unlikely(!alloc_cpumask_var(&cmd.mask, GFP_KERNEL)))
-               return 0;
-
        cpumask_copy(cmd.mask, mask);
 
        drv_read(&cmd);
 
-       free_cpumask_var(cmd.mask);
-
        dprintk("get_cur_val = %u\n", cmd.val);
 
        return cmd.val;
index c0601c2848a159758b472d3dd83d42baed02339a..a649a4ccad43213ae1bb20cd62b48f65791a6ae7 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/e820.h>
 #include <asm/trampoline.h>
 #include <asm/setup.h>
+#include <asm/smp.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_X86_32
index 9e268b6b204e1e3b34d639061aa43fcd9e0bbc3f..90dfae511a41e1dcf7fcf188b94d13c123780606 100644 (file)
@@ -534,7 +534,7 @@ static int vmalloc_fault(unsigned long address)
           happen within a race in page table update. In the later
           case just flush. */
 
-       pgd = pgd_offset(current->mm ?: &init_mm, address);
+       pgd = pgd_offset(current->active_mm, address);
        pgd_ref = pgd_offset_k(address);
        if (pgd_none(*pgd_ref))
                return -1;
index 4b1d4ac960f1d87e39880372fa2cd29b703e1b29..8df436ff7068b4840bdbcf610e357797ae387ae5 100644 (file)
@@ -156,7 +156,7 @@ static volatile int fdc_busy = -1;
 static volatile int fdc_nested;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
  
-static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
+static DECLARE_COMPLETION(motor_on_completion);
 
 static volatile int selected = -1;     /* currently selected drive */
 
@@ -184,8 +184,7 @@ static unsigned char mfmencode[16]={
 static unsigned char mfmdecode[128];
 
 /* floppy internal millisecond timer stuff */
-static volatile int ms_busy = -1;
-static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
+static DECLARE_COMPLETION(ms_wait_completion);
 #define MS_TICKS ((amiga_eclock+50)/1000)
 
 /*
@@ -211,8 +210,7 @@ static int fd_device[4] = { 0, 0, 0, 0 };
 
 static irqreturn_t ms_isr(int irq, void *dummy)
 {
-       ms_busy = -1;
-       wake_up(&ms_wait);
+       complete(&ms_wait_completion);
        return IRQ_HANDLED;
 }
 
@@ -220,19 +218,17 @@ static irqreturn_t ms_isr(int irq, void *dummy)
    A more generic routine would do a schedule a la timer.device */
 static void ms_delay(int ms)
 {
-       unsigned long flags;
        int ticks;
+       static DEFINE_MUTEX(mutex);
+
        if (ms > 0) {
-               local_irq_save(flags);
-               while (ms_busy == 0)
-                       sleep_on(&ms_wait);
-               ms_busy = 0;
-               local_irq_restore(flags);
+               mutex_lock(&mutex);
                ticks = MS_TICKS*ms-1;
                ciaa.tblo=ticks%256;
                ciaa.tbhi=ticks/256;
                ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
-               sleep_on(&ms_wait);
+               wait_for_completion(&ms_wait_completion);
+               mutex_unlock(&mutex);
        }
 }
 
@@ -254,8 +250,7 @@ static void get_fdc(int drive)
        printk("get_fdc: drive %d  fdc_busy %d  fdc_nested %d\n",drive,fdc_busy,fdc_nested);
 #endif
        local_irq_save(flags);
-       while (!try_fdc(drive))
-               sleep_on(&fdc_wait);
+       wait_event(fdc_wait, try_fdc(drive));
        fdc_busy = drive;
        fdc_nested++;
        local_irq_restore(flags);
@@ -330,7 +325,7 @@ static void fd_deselect (int drive)
 static void motor_on_callback(unsigned long nr)
 {
        if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
-               wake_up (&motor_wait);
+               complete_all(&motor_on_completion);
        } else {
                motor_on_timer.expires = jiffies + HZ/10;
                add_timer(&motor_on_timer);
@@ -347,11 +342,12 @@ static int fd_motor_on(int nr)
                unit[nr].motor = 1;
                fd_select(nr);
 
+               INIT_COMPLETION(motor_on_completion);
                motor_on_timer.data = nr;
                mod_timer(&motor_on_timer, jiffies + HZ/2);
 
                on_attempts = 10;
-               sleep_on (&motor_wait);
+               wait_for_completion(&motor_on_completion);
                fd_deselect(nr);
        }
 
@@ -582,8 +578,7 @@ static void raw_read(int drive)
 {
        drive&=3;
        get_fdc(drive);
-       while (block_flag)
-               sleep_on(&wait_fd_block);
+       wait_event(wait_fd_block, !block_flag);
        fd_select(drive);
        /* setup adkcon bits correctly */
        custom.adkcon = ADK_MSBSYNC;
@@ -598,8 +593,7 @@ static void raw_read(int drive)
 
        block_flag = 1;
 
-       while (block_flag)
-               sleep_on (&wait_fd_block);
+       wait_event(wait_fd_block, !block_flag);
 
        custom.dsklen = 0;
        fd_deselect(drive);
@@ -616,8 +610,7 @@ static int raw_write(int drive)
                rel_fdc();
                return 0;
        }
-       while (block_flag)
-               sleep_on(&wait_fd_block);
+       wait_event(wait_fd_block, !block_flag);
        fd_select(drive);
        /* clear adkcon bits */
        custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
@@ -1294,8 +1287,7 @@ static int non_int_flush_track (unsigned long nr)
                        writepending = 0;
                        return 0;
                }
-               while (block_flag == 2)
-                       sleep_on (&wait_fd_block);
+               wait_event(wait_fd_block, block_flag != 2);
        }
        else {
                local_irq_restore(flags);
index 4e0cfdeab1462a8b16641c6ef54cc480ccbe8fc9..a58869ea8513826d32af82688c661b50fdd90071 100644 (file)
@@ -1963,6 +1963,7 @@ static int __init rs_init(void)
 {
        unsigned long flags;
        struct serial_state * state;
+       int error;
 
        if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
                return -ENODEV;
@@ -1975,8 +1976,11 @@ static int __init rs_init(void)
         *  We request SERDAT and SERPER only, because the serial registers are
         *  too spreaded over the custom register space
         */
-       if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, "amiserial [Paula]"))
-               return -EBUSY;
+       if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4,
+                               "amiserial [Paula]")) {
+               error = -EBUSY;
+               goto fail_put_tty_driver;
+       }
 
        IRQ_ports = NULL;
 
@@ -1997,8 +2001,9 @@ static int __init rs_init(void)
        serial_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(serial_driver, &serial_ops);
 
-       if (tty_register_driver(serial_driver))
-               panic("Couldn't register serial driver\n");
+       error = tty_register_driver(serial_driver);
+       if (error)
+               goto fail_release_mem_region;
 
        state = rs_table;
        state->magic = SSTATE_MAGIC;
@@ -2024,8 +2029,14 @@ static int __init rs_init(void)
        local_irq_save(flags);
 
        /* set ISRs, and then disable the rx interrupts */
-       request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
-       request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, "serial RX", state);
+       error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
+       if (error)
+               goto fail_unregister;
+
+       error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
+                           "serial RX", state);
+       if (error)
+               goto fail_free_irq;
 
        /* turn off Rx and Tx interrupts */
        custom.intena = IF_RBF | IF_TBE;
@@ -2045,6 +2056,16 @@ static int __init rs_init(void)
        ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
 
        return 0;
+
+fail_free_irq:
+       free_irq(IRQ_AMIGA_TBE, state);
+fail_unregister:
+       tty_unregister_driver(serial_driver);
+fail_release_mem_region:
+       release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
+fail_put_tty_driver:
+       put_tty_driver(serial_driver);
+       return error;
 }
 
 static __exit void rs_exit(void) 
@@ -2064,6 +2085,9 @@ static __exit void rs_exit(void)
          kfree(info);
        }
 
+       free_irq(IRQ_AMIGA_TBE, rs_table);
+       free_irq(IRQ_AMIGA_RBF, rs_table);
+
        release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
 }
 
index 33872a219df6b57355f5dd1eb5e988f9e8bb89d3..33a2b531802ecd3fcf839bb2d5edae5406daa437 100644 (file)
@@ -718,6 +718,7 @@ static int __init a2232board_init(void)
        u_char *from;
        volatile u_char *to;
        volatile struct a2232memory *mem;
+       int error, i;
 
 #ifdef CONFIG_SMP
        return -ENODEV; /* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
@@ -797,8 +798,15 @@ static int __init a2232board_init(void)
        */
        if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
 
-       request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, "A2232 serial VBL", a2232_driver_ID);
-       return 0;
+       error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
+                           "A2232 serial VBL", a2232_driver_ID);
+       if (error) {
+               for (i = 0; i < nr_a2232; i++)
+                       zorro_release_device(zd_a2232[i]);
+               tty_unregister_driver(a2232_driver);
+               put_tty_driver(a2232_driver);
+       }
+       return error;
 }
 
 static void __exit a2232board_exit(void)
index 0e8234bd0e19b6d178658dcd6e698d9d6f217854..994e1a58b987c0616b71fa485e7a8ea608959a39 100644 (file)
@@ -198,6 +198,7 @@ static void scc_init_portstructs(void)
 static int mvme147_scc_init(void)
 {
        struct scc_port *port;
+       int error;
 
        printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
        /* Init channel A */
@@ -207,14 +208,23 @@ static int mvme147_scc_init(void)
        port->datap = port->ctrlp + 1;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-A TX", port);
-       request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail;
+       error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-A status", port);
-       request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_tx;
+       error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-A RX", port);
-       request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_stat;
+       error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_rx;
+
        {
                SCC_ACCESS_INIT(port);
 
@@ -234,14 +244,23 @@ static int mvme147_scc_init(void)
        port->datap = port->ctrlp + 1;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-B TX", port);
-       request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_spcond;
+       error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-B status", port);
-       request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_b_tx;
+       error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-B RX", port);
-       request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_stat;
+       error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_rx;
+
        {
                SCC_ACCESS_INIT(port);
 
@@ -257,6 +276,23 @@ static int mvme147_scc_init(void)
        scc_init_drivers();
 
        return 0;
+
+fail_free_b_rx:
+       free_irq(MVME147_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+       free_irq(MVME147_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+       free_irq(MVME147_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+       free_irq(MVME147_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+       free_irq(MVME147_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+       free_irq(MVME147_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+       free_irq(MVME147_IRQ_SCCA_TX, port);
+fail:
+       return error;
 }
 #endif
 
@@ -265,6 +301,7 @@ static int mvme147_scc_init(void)
 static int mvme162_scc_init(void)
 {
        struct scc_port *port;
+       int error;
 
        if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
                return (-ENODEV);
@@ -277,14 +314,23 @@ static int mvme162_scc_init(void)
        port->datap = port->ctrlp + 2;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-A TX", port);
-       request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail;
+       error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-A status", port);
-       request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_tx;
+       error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-A RX", port);
-       request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_stat;
+       error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_rx;
+
        {
                SCC_ACCESS_INIT(port);
 
@@ -304,14 +350,22 @@ static int mvme162_scc_init(void)
        port->datap = port->ctrlp + 2;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-B TX", port);
-       request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_spcond;
+       error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-B status", port);
-       request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_b_tx;
+       error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-B RX", port);
-       request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_stat;
+       error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_rx;
 
        {
                SCC_ACCESS_INIT(port);  /* Either channel will do */
@@ -328,6 +382,23 @@ static int mvme162_scc_init(void)
        scc_init_drivers();
 
        return 0;
+
+fail_free_b_rx:
+       free_irq(MVME162_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+       free_irq(MVME162_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+       free_irq(MVME162_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+       free_irq(MVME162_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+       free_irq(MVME162_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+       free_irq(MVME162_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+       free_irq(MVME162_IRQ_SCCA_TX, port);
+fail:
+       return error;
 }
 #endif
 
@@ -336,6 +407,7 @@ static int mvme162_scc_init(void)
 static int bvme6000_scc_init(void)
 {
        struct scc_port *port;
+       int error;
 
        printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
        /* Init channel A */
@@ -345,14 +417,23 @@ static int bvme6000_scc_init(void)
        port->datap = port->ctrlp + 4;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-A TX", port);
-       request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail;
+       error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-A status", port);
-       request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_tx;
+       error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-A RX", port);
-       request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_stat;
+       error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-A special cond", port);
+       if (error)
+               goto fail_free_a_rx;
+
        {
                SCC_ACCESS_INIT(port);
 
@@ -372,14 +453,22 @@ static int bvme6000_scc_init(void)
        port->datap = port->ctrlp + 4;
        port->port_a = &scc_ports[0];
        port->port_b = &scc_ports[1];
-       request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+       error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
                            "SCC-B TX", port);
-       request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_a_spcond;
+       error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
                            "SCC-B status", port);
-       request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+       if (error)
+               goto fail_free_b_tx;
+       error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
                            "SCC-B RX", port);
-       request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
-                           "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_stat;
+       error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
+                           IRQF_DISABLED, "SCC-B special cond", port);
+       if (error)
+               goto fail_free_b_rx;
 
        {
                SCC_ACCESS_INIT(port);  /* Either channel will do */
@@ -393,6 +482,23 @@ static int bvme6000_scc_init(void)
        scc_init_drivers();
 
        return 0;
+
+fail:
+       free_irq(BVME_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+       free_irq(BVME_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+       free_irq(BVME_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+       free_irq(BVME_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+       free_irq(BVME_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+       free_irq(BVME_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+       free_irq(BVME_IRQ_SCCB_SPCOND, port);
+fail_free_b_rx:
+       return error;
 }
 #endif
 
index f464630388471a69fb048d41f60c4d186821df3e..ee1a3b59bd4e0a76b48a34f32a8973ba767eb058 100644 (file)
@@ -58,20 +58,25 @@ static ssize_t dio_show_resource(struct device *dev, struct device_attribute *at
        struct dio_dev *d = to_dio_dev(dev);
 
        return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
-                      dio_resource_start(d), dio_resource_end(d),
+                      (unsigned long)dio_resource_start(d),
+                      (unsigned long)dio_resource_end(d),
                       dio_resource_flags(d));
 }
 static DEVICE_ATTR(resource, S_IRUGO, dio_show_resource, NULL);
 
-void dio_create_sysfs_dev_files(struct dio_dev *d)
+int dio_create_sysfs_dev_files(struct dio_dev *d)
 {
        struct device *dev = &d->dev;
+       int error;
 
        /* current configuration's attributes */
-       device_create_file(dev, &dev_attr_id);
-       device_create_file(dev, &dev_attr_ipl);
-       device_create_file(dev, &dev_attr_secid);
-       device_create_file(dev, &dev_attr_name);
-       device_create_file(dev, &dev_attr_resource);
+       if ((error = device_create_file(dev, &dev_attr_id)) ||
+           (error = device_create_file(dev, &dev_attr_ipl)) ||
+           (error = device_create_file(dev, &dev_attr_secid)) ||
+           (error = device_create_file(dev, &dev_attr_name)) ||
+           (error = device_create_file(dev, &dev_attr_resource)))
+               return error;
+
+       return 0;
 }
 
index 07f274f853d95f5dc0cf8b671e989fca3a65742f..10c3c498358c0d27b0bbfa3c979f77f4841758be 100644 (file)
@@ -173,6 +173,7 @@ static int __init dio_init(void)
        mm_segment_t fs;
        int i;
        struct dio_dev *dev;
+       int error;
 
        if (!MACH_IS_HP300)
                return 0;
@@ -182,7 +183,11 @@ static int __init dio_init(void)
        /* Initialize the DIO bus */ 
        INIT_LIST_HEAD(&dio_bus.devices);
        strcpy(dio_bus.dev.bus_id, "dio");
-       device_register(&dio_bus.dev);
+       error = device_register(&dio_bus.dev);
+       if (error) {
+               pr_err("DIO: Error registering dio_bus\n");
+               return error;
+       }
 
        /* Request all resources */
        dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
@@ -252,8 +257,15 @@ static int __init dio_init(void)
 
                if (scode >= DIOII_SCBASE)
                        iounmap(va);
-               device_register(&dev->dev);
-               dio_create_sysfs_dev_files(dev);
+               error = device_register(&dev->dev);
+               if (error) {
+                       pr_err("DIO: Error registering device %s\n",
+                              dev->name);
+                       continue;
+               }
+               error = dio_create_sysfs_dev_files(dev);
+               if (error)
+                       dev_err(&dev->dev, "Error creating sysfs files\n");
         }
        return 0;
 }
index e39e33e797da70d447f4f4b090ad9bb9163fe157..be2b657546efe3d96e2403476c8c896d774959e4 100644 (file)
@@ -28,7 +28,7 @@ obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
 
 # Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
@@ -72,7 +72,7 @@ obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
 obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
 obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
 obj-$(CONFIG_FB_ACORN)            += acornfb.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
+obj-$(CONFIG_FB_ATARI)            += atafb.o c2p_iplan2.o atafb_mfb.o \
                                      atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
 obj-$(CONFIG_FB_MAC)              += macfb.o
 obj-$(CONFIG_FB_HECUBA)           += hecubafb.o
index b8e9a8682f2de98011502b762062285febbd6552..100f236614650f42337d7007adb5f32cf09ebf77 100644 (file)
@@ -2159,9 +2159,9 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
                        src += pitch;
                }
        } else {
-               c2p(info->screen_base, image->data, dx, dy, width, height,
-                   par->next_line, par->next_plane, image->width,
-                   info->var.bits_per_pixel);
+               c2p_planar(info->screen_base, image->data, dx, dy, width,
+                          height, par->next_line, par->next_plane,
+                          image->width, info->var.bits_per_pixel);
        }
 }
 
index 77eb8b34fbfaee0e478ce39eef506dd605826212..8058572a74283303f178d03d0e97e64632c85099 100644 (file)
@@ -122,7 +122,6 @@ static struct atafb_par {
        void *screen_base;
        int yres_virtual;
        u_long next_line;
-       u_long next_plane;
 #if defined ATAFB_TT || defined ATAFB_STE
        union {
                struct {
@@ -149,6 +148,7 @@ static struct atafb_par {
                        short mono;
                        short ste_mode;
                        short bpp;
+                       u32 pseudo_palette[16];
                } falcon;
 #endif
                /* Nothing needed for external mode */
@@ -614,7 +614,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
        fix->xpanstep = 0;
        fix->ypanstep = 1;
        fix->ywrapstep = 0;
-       fix->line_length = 0;
+       fix->line_length = par->next_line;
        fix->accel = FB_ACCEL_ATARIBLITT;
        return 0;
 }
@@ -691,6 +691,7 @@ static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
                return -EINVAL;
        par->yres_virtual = yres_virtual;
        par->screen_base = screen_base + var->yoffset * linelen;
+       par->next_line = linelen;
        return 0;
 }
 
@@ -884,10 +885,6 @@ static int vdl_prescale[4][3] = {
 /* Default hsync timing [mon_type] in picoseconds */
 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 
-#ifdef FBCON_HAS_CFB16
-static u16 fbcon_cfb16_cmap[16];
-#endif
-
 static inline int hxx_prescale(struct falcon_hw *hw)
 {
        return hw->ste_mode ? 16
@@ -918,7 +915,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
                fix->visual = FB_VISUAL_TRUECOLOR;
                fix->xpanstep = 2;
        }
-       fix->line_length = 0;
+       fix->line_length = par->next_line;
        fix->accel = FB_ACCEL_ATARIBLITT;
        return 0;
 }
@@ -1394,14 +1391,7 @@ set_screen_base:
        par->screen_base = screen_base + var->yoffset * linelen;
        par->hw.falcon.xoffset = 0;
 
-       // FIXME!!! sort of works, no crash
-       //par->next_line = linelen;
-       //par->next_plane = yres_virtual * linelen;
        par->next_line = linelen;
-       par->next_plane = 2;
-       // crashes
-       //par->next_plane = linelen;
-       //par->next_line  = yres_virtual * linelen;
 
        return 0;
 }
@@ -1735,10 +1725,10 @@ static int falcon_setcolreg(unsigned int regno, unsigned int red,
                        (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
                        (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
                        ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-#ifdef FBCON_HAS_CFB16
-               fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
-                                          ((green & 0xfc00) >> 5) |
-                                          ((blue & 0xf800) >> 11));
+#ifdef ATAFB_FALCON
+               ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
+                                                      ((green & 0xfc00) >> 5) |
+                                                      ((blue & 0xf800) >> 11));
 #endif
        }
        return 0;
@@ -1852,7 +1842,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
                fix->ypanstep = 0;
        }
        fix->ywrapstep = 0;
-       fix->line_length = 0;
+       fix->line_length = par->next_line;
        fix->accel = FB_ACCEL_ATARIBLITT;
        return 0;
 }
@@ -1910,6 +1900,7 @@ static int stste_decode_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        par->yres_virtual = yres_virtual;
        par->screen_base = screen_base + var->yoffset * linelen;
+       par->next_line = linelen;
        return 0;
 }
 
@@ -2169,7 +2160,7 @@ static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
        fix->xpanstep = 0;
        fix->ypanstep = 0;
        fix->ywrapstep = 0;
-       fix->line_length = 0;
+       fix->line_length = par->next_line;
        return 0;
 }
 
@@ -2184,6 +2175,8 @@ static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
            var->xoffset > 0 ||
            var->yoffset > 0)
                return -EINVAL;
+
+       par->next_line = external_xres_virtual * external_depth / 8;
        return 0;
 }
 
@@ -2443,42 +2436,6 @@ static void atafb_set_disp(struct fb_info *info)
        atafb_get_fix(&info->fix, info);
 
        info->screen_base = (void *)info->fix.smem_start;
-
-       switch (info->fix.type) {
-       case FB_TYPE_INTERLEAVED_PLANES:
-               switch (info->var.bits_per_pixel) {
-               case 2:
-                       // display->dispsw = &fbcon_iplan2p2;
-                       break;
-               case 4:
-                       // display->dispsw = &fbcon_iplan2p4;
-                       break;
-               case 8:
-                       // display->dispsw = &fbcon_iplan2p8;
-                       break;
-               }
-               break;
-       case FB_TYPE_PACKED_PIXELS:
-               switch (info->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-               case 1:
-                       // display->dispsw = &fbcon_mfb;
-                       break;
-#endif
-#ifdef FBCON_HAS_CFB8
-               case 8:
-                       // display->dispsw = &fbcon_cfb8;
-                       break;
-#endif
-#ifdef FBCON_HAS_CFB16
-               case 16:
-                       // display->dispsw = &fbcon_cfb16;
-                       // display->dispsw_data = fbcon_cfb16_cmap;
-                       break;
-#endif
-               }
-               break;
-       }
 }
 
 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2549,6 +2506,13 @@ static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        if (!rect->width || !rect->height)
                return;
 
+#ifdef ATAFB_FALCON
+       if (info->var.bits_per_pixel == 16) {
+               cfb_fillrect(info, rect);
+               return;
+       }
+#endif
+
        /*
         * We could use hardware clipping but on many cards you get around
         * hardware clipping by writing to framebuffer directly.
@@ -2583,6 +2547,13 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        u32 dx, dy, sx, sy, width, height;
        int rev_copy = 0;
 
+#ifdef ATAFB_FALCON
+       if (info->var.bits_per_pixel == 16) {
+               cfb_copyarea(info, area);
+               return;
+       }
+#endif
+
        /* clip the destination */
        x2 = area->dx + area->width;
        y2 = area->dy + area->height;
@@ -2632,6 +2603,13 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
        const char *src;
        u32 dx, dy, width, height, pitch;
 
+#ifdef ATAFB_FALCON
+       if (info->var.bits_per_pixel == 16) {
+               cfb_imageblit(info, image);
+               return;
+       }
+#endif
+
        /*
         * We could use hardware clipping but on many cards you get around
         * hardware clipping by writing to framebuffer directly like we are
@@ -2676,10 +2654,9 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
                        src += pitch;
                }
        } else {
-               // only used for logo; broken
-               c2p(info->screen_base, image->data, dx, dy, width, height,
-                   par->next_line, par->next_plane, image->width,
-                   info->var.bits_per_pixel);
+               c2p_iplan2(info->screen_base, image->data, dx, dy, width,
+                          height, par->next_line, image->width,
+                          info->var.bits_per_pixel);
        }
 }
 
@@ -3098,8 +3075,7 @@ int __init atafb_setup(char *options)
 
 int __init atafb_init(void)
 {
-       int pad;
-       int detected_mode;
+       int pad, detected_mode, error;
        unsigned int defmode = 0;
        unsigned long mem_req;
 
@@ -3139,8 +3115,12 @@ int __init atafb_init(void)
                        printk("atafb_init: initializing Falcon hw\n");
                        fbhw = &falcon_switch;
                        atafb_ops.fb_setcolreg = &falcon_setcolreg;
-                       request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
-                                   "framebuffer/modeswitch", falcon_vbl_switcher);
+                       error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
+                                           IRQ_TYPE_PRIO,
+                                           "framebuffer/modeswitch",
+                                           falcon_vbl_switcher);
+                       if (error)
+                               return error;
                        defmode = DEFMODE_F30;
                        break;
                }
@@ -3225,6 +3205,10 @@ int __init atafb_init(void)
        // tries to read from HW which may not be initialized yet
        // so set sane var first, then call atafb_set_par
        atafb_get_var(&fb_info.var, &fb_info);
+
+#ifdef ATAFB_FALCON
+       fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
+#endif
        fb_info.flags = FBINFO_FLAG_DEFAULT;
 
        if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
diff --git a/drivers/video/c2p.c b/drivers/video/c2p.c
deleted file mode 100644 (file)
index 376bc07..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003 Geert Uytterhoeven
- *
- *  NOTES:
- *    - This code was inspired by Scout's C2P tutorial
- *    - It assumes to run on a big endian system
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include "c2p.h"
-
-
-    /*
-     *  Basic transpose step
-     */
-
-#define _transp(d, i1, i2, shift, mask)                        \
-    do {                                               \
-       u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;      \
-       d[i1] ^= t;                                     \
-       d[i2] ^= t << shift;                            \
-    } while (0)
-
-static inline u32 get_mask(int n)
-{
-    switch (n) {
-       case 1:
-           return 0x55555555;
-           break;
-
-       case 2:
-           return 0x33333333;
-           break;
-
-       case 4:
-           return 0x0f0f0f0f;
-           break;
-
-       case 8:
-           return 0x00ff00ff;
-           break;
-
-       case 16:
-           return 0x0000ffff;
-           break;
-    }
-    return 0;
-}
-
-#define transp_nx1(d, n)                               \
-    do {                                               \
-       u32 mask = get_mask(n);                         \
-       /* First block */                               \
-       _transp(d, 0, 1, n, mask);                      \
-       /* Second block */                              \
-       _transp(d, 2, 3, n, mask);                      \
-       /* Third block */                               \
-       _transp(d, 4, 5, n, mask);                      \
-       /* Fourth block */                              \
-       _transp(d, 6, 7, n, mask);                      \
-    } while (0)
-
-#define transp_nx2(d, n)                               \
-    do {                                               \
-       u32 mask = get_mask(n);                         \
-       /* First block */                               \
-       _transp(d, 0, 2, n, mask);                      \
-       _transp(d, 1, 3, n, mask);                      \
-       /* Second block */                              \
-       _transp(d, 4, 6, n, mask);                      \
-       _transp(d, 5, 7, n, mask);                      \
-    } while (0)
-
-#define transp_nx4(d, n)                               \
-    do {                                               \
-       u32 mask = get_mask(n);                         \
-       _transp(d, 0, 4, n, mask);                      \
-       _transp(d, 1, 5, n, mask);                      \
-       _transp(d, 2, 6, n, mask);                      \
-       _transp(d, 3, 7, n, mask);                      \
-    } while (0)
-
-#define transp(d, n, m)        transp_nx ## m(d, n)
-
-
-    /*
-     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
-     *  containing
-     *    - 32 8-bit chunky pixels on input
-     *    - permuted planar data on output
-     */
-
-static void c2p_8bpp(u32 d[8])
-{
-    transp(d, 16, 4);
-    transp(d, 8, 2);
-    transp(d, 4, 1);
-    transp(d, 2, 4);
-    transp(d, 1, 2);
-}
-
-
-    /*
-     *  Array containing the permution indices of the planar data after c2p
-     */
-
-static const int perm_c2p_8bpp[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
-
-
-    /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline unsigned long comp(unsigned long a, unsigned long b,
-                                unsigned long mask)
-{
-       return ((a ^ b) & mask) ^ b;
-}
-
-
-    /*
-     *  Store a full block of planar data after c2p conversion
-     */
-
-static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
-{
-    int i;
-
-    for (i = 0; i < bpp; i++, dst += dst_inc)
-       *(u32 *)dst = d[perm_c2p_8bpp[i]];
-}
-
-
-    /*
-     *  Store a partial block of planar data after c2p conversion
-     */
-
-static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
-                                      u32 d[8], u32 mask)
-{
-    int i;
-
-    for (i = 0; i < bpp; i++, dst += dst_inc)
-       *(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
-}
-
-
-    /*
-     *  c2p - Copy 8-bit chunky image data to a planar frame buffer
-     *  @dst: Starting address of the planar frame buffer
-     *  @dx: Horizontal destination offset (in pixels)
-     *  @dy: Vertical destination offset (in pixels)
-     *  @width: Image width (in pixels)
-     *  @height: Image height (in pixels)
-     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
-     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
-     *  @src_nextline: Image offset to the next line (in bytes)
-     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
-     */
-
-void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
-        u32 dst_nextline, u32 dst_nextplane, u32 src_nextline, u32 bpp)
-{
-    int dst_idx;
-    u32 d[8], first, last, w;
-    const u8 *c;
-    u8 *p;
-
-    dst += dy*dst_nextline+(dx & ~31);
-    dst_idx = dx % 32;
-    first = ~0UL >> dst_idx;
-    last = ~(~0UL >> ((dst_idx+width) % 32));
-    while (height--) {
-       c = src;
-       p = dst;
-       w = width;
-       if (dst_idx+width <= 32) {
-           /* Single destination word */
-           first &= last;
-           memset(d, 0, sizeof(d));
-           memcpy((u8 *)d+dst_idx, c, width);
-           c += width;
-           c2p_8bpp(d);
-           store_planar_masked(p, dst_nextplane, bpp, d, first);
-           p += 4;
-       } else {
-           /* Multiple destination words */
-           w = width;
-           /* Leading bits */
-           if (dst_idx) {
-               w = 32 - dst_idx;
-               memset(d, 0, dst_idx);
-               memcpy((u8 *)d+dst_idx, c, w);
-               c += w;
-               c2p_8bpp(d);
-               store_planar_masked(p, dst_nextplane, bpp, d, first);
-               p += 4;
-               w = width-w;
-           }
-           /* Main chunk */
-           while (w >= 32) {
-               memcpy(d, c, 32);
-               c += 32;
-               c2p_8bpp(d);
-               store_planar(p, dst_nextplane, bpp, d);
-               p += 4;
-               w -= 32;
-           }
-           /* Trailing bits */
-           w %= 32;
-           if (w > 0) {
-               memcpy(d, c, w);
-               memset((u8 *)d+w, 0, 32-w);
-               c2p_8bpp(d);
-               store_planar_masked(p, dst_nextplane, bpp, d, last);
-           }
-       }
-       src += src_nextline;
-       dst += dst_nextline;
-    }
-}
-EXPORT_SYMBOL_GPL(c2p);
-
-MODULE_LICENSE("GPL");
index c77cbf17e043c5c3741ae2e7de1e2b6284ce1ecd..6c38d40427d8d8da12cc084705fb76f80a652b8d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Fast C2P (Chunky-to-Planar) Conversion
  *
- *  Copyright (C) 2003 Geert Uytterhoeven
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive
 
 #include <linux/types.h>
 
-extern void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
-               u32 dst_nextline, u32 dst_nextplane, u32 src_nextline,
-               u32 bpp);
+extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+                      u32 height, u32 dst_nextline, u32 dst_nextplane,
+                      u32 src_nextline, u32 bpp);
 
+extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+                      u32 height, u32 dst_nextline, u32 src_nextline,
+                      u32 bpp);
diff --git a/drivers/video/c2p_core.h b/drivers/video/c2p_core.h
new file mode 100644 (file)
index 0000000..e1035a8
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  NOTES:
+ *    - This code was inspired by Scout's C2P tutorial
+ *    - It assumes to run on a big endian system
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+
+    /*
+     *  Basic transpose step
+     */
+
+static inline void _transp(u32 d[], unsigned int i1, unsigned int i2,
+                          unsigned int shift, u32 mask)
+{
+       u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;
+
+       d[i1] ^= t;
+       d[i2] ^= t << shift;
+}
+
+
+extern void c2p_unsupported(void);
+
+static inline u32 get_mask(unsigned int n)
+{
+       switch (n) {
+       case 1:
+               return 0x55555555;
+
+       case 2:
+               return 0x33333333;
+
+       case 4:
+               return 0x0f0f0f0f;
+
+       case 8:
+               return 0x00ff00ff;
+
+       case 16:
+               return 0x0000ffff;
+       }
+
+       c2p_unsupported();
+       return 0;
+}
+
+
+    /*
+     *  Transpose operations on 8 32-bit words
+     */
+
+static inline void transp8(u32 d[], unsigned int n, unsigned int m)
+{
+       u32 mask = get_mask(n);
+
+       switch (m) {
+       case 1:
+               /* First n x 1 block */
+               _transp(d, 0, 1, n, mask);
+               /* Second n x 1 block */
+               _transp(d, 2, 3, n, mask);
+               /* Third n x 1 block */
+               _transp(d, 4, 5, n, mask);
+               /* Fourth n x 1 block */
+               _transp(d, 6, 7, n, mask);
+               return;
+
+       case 2:
+               /* First n x 2 block */
+               _transp(d, 0, 2, n, mask);
+               _transp(d, 1, 3, n, mask);
+               /* Second n x 2 block */
+               _transp(d, 4, 6, n, mask);
+               _transp(d, 5, 7, n, mask);
+               return;
+
+       case 4:
+               /* Single n x 4 block */
+               _transp(d, 0, 4, n, mask);
+               _transp(d, 1, 5, n, mask);
+               _transp(d, 2, 6, n, mask);
+               _transp(d, 3, 7, n, mask);
+               return;
+       }
+
+       c2p_unsupported();
+}
+
+
+    /*
+     *  Transpose operations on 4 32-bit words
+     */
+
+static inline void transp4(u32 d[], unsigned int n, unsigned int m)
+{
+       u32 mask = get_mask(n);
+
+       switch (m) {
+       case 1:
+               /* First n x 1 block */
+               _transp(d, 0, 1, n, mask);
+               /* Second n x 1 block */
+               _transp(d, 2, 3, n, mask);
+               return;
+
+       case 2:
+               /* Single n x 2 block */
+               _transp(d, 0, 2, n, mask);
+               _transp(d, 1, 3, n, mask);
+               return;
+       }
+
+       c2p_unsupported();
+}
+
+
+    /*
+     *  Transpose operations on 4 32-bit words (reverse order)
+     */
+
+static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
+{
+       u32 mask = get_mask(n);
+
+       switch (m) {
+       case 2:
+               /* Single n x 2 block */
+               _transp(d, 2, 0, n, mask);
+               _transp(d, 3, 1, n, mask);
+               return;
+       }
+
+       c2p_unsupported();
+}
+
+
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline u32 comp(u32 a, u32 b, u32 mask)
+{
+       return ((a ^ b) & mask) ^ b;
+}
diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/c2p_iplan2.c
new file mode 100644 (file)
index 0000000..19156dc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
+     *  containing
+     *    - 16 8-bit chunky pixels on input
+     *    - permutated planar data (2 planes per 32-bit word) on output
+     */
+
+static void c2p_16x8(u32 d[4])
+{
+       transp4(d, 8, 2);
+       transp4(d, 1, 2);
+       transp4x(d, 16, 2);
+       transp4x(d, 2, 2);
+       transp4(d, 4, 1);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
+
+
+    /*
+     *  Store a full block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
+{
+       int i;
+
+       for (i = 0; i < bpp/2; i++, dst += 4)
+               put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
+}
+
+
+    /*
+     *  Store a partial block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
+{
+       int i;
+
+       for (i = 0; i < bpp/2; i++, dst += 4)
+               put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
+                                       get_unaligned_be32(dst), mask),
+                                  dst);
+}
+
+
+    /*
+     *  c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
+     *  frame buffer with 2 bytes of interleave
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
+     */
+
+void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+               u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
+{
+       union {
+               u8 pixels[16];
+               u32 words[4];
+       } d;
+       u32 dst_idx, first, last, w;
+       const u8 *c;
+       void *p;
+
+       dst += dy*dst_nextline+(dx & ~15)*bpp;
+       dst_idx = dx % 16;
+       first = 0xffffU >> dst_idx;
+       first |= first << 16;
+       last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
+       last |= last << 16;
+       while (height--) {
+               c = src;
+               p = dst;
+               w = width;
+               if (dst_idx+width <= 16) {
+                       /* Single destination word */
+                       first &= last;
+                       memset(d.pixels, 0, sizeof(d));
+                       memcpy(d.pixels+dst_idx, c, width);
+                       c += width;
+                       c2p_16x8(d.words);
+                       store_iplan2_masked(p, bpp, d.words, first);
+                       p += bpp*2;
+               } else {
+                       /* Multiple destination words */
+                       w = width;
+                       /* Leading bits */
+                       if (dst_idx) {
+                               w = 16 - dst_idx;
+                               memset(d.pixels, 0, dst_idx);
+                               memcpy(d.pixels+dst_idx, c, w);
+                               c += w;
+                               c2p_16x8(d.words);
+                               store_iplan2_masked(p, bpp, d.words, first);
+                               p += bpp*2;
+                               w = width-w;
+                       }
+                       /* Main chunk */
+                       while (w >= 16) {
+                               memcpy(d.pixels, c, 16);
+                               c += 16;
+                               c2p_16x8(d.words);
+                               store_iplan2(p, bpp, d.words);
+                               p += bpp*2;
+                               w -= 16;
+                       }
+                       /* Trailing bits */
+                       w %= 16;
+                       if (w > 0) {
+                               memcpy(d.pixels, c, w);
+                               memset(d.pixels+w, 0, 16-w);
+                               c2p_16x8(d.words);
+                               store_iplan2_masked(p, bpp, d.words, last);
+                       }
+               }
+               src += src_nextline;
+               dst += dst_nextline;
+       }
+}
+EXPORT_SYMBOL_GPL(c2p_iplan2);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/c2p_planar.c b/drivers/video/c2p_planar.c
new file mode 100644 (file)
index 0000000..ec7ac85
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
+     *  containing
+     *    - 32 8-bit chunky pixels on input
+     *    - permutated planar data (1 plane per 32-bit word) on output
+     */
+
+static void c2p_32x8(u32 d[8])
+{
+       transp8(d, 16, 4);
+       transp8(d, 8, 2);
+       transp8(d, 4, 1);
+       transp8(d, 2, 4);
+       transp8(d, 1, 2);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
+
+
+    /*
+     *  Store a full block of planar data after c2p conversion
+     */
+
+static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
+{
+       int i;
+
+       for (i = 0; i < bpp; i++, dst += dst_inc)
+               put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
+}
+
+
+    /*
+     *  Store a partial block of planar data after c2p conversion
+     */
+
+static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
+                                      u32 d[8], u32 mask)
+{
+       int i;
+
+       for (i = 0; i < bpp; i++, dst += dst_inc)
+               put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
+                                       get_unaligned_be32(dst), mask),
+                                  dst);
+}
+
+
+    /*
+     *  c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
+     */
+
+void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+               u32 height, u32 dst_nextline, u32 dst_nextplane,
+               u32 src_nextline, u32 bpp)
+{
+       union {
+               u8 pixels[32];
+               u32 words[8];
+       } d;
+       u32 dst_idx, first, last, w;
+       const u8 *c;
+       void *p;
+
+       dst += dy*dst_nextline+(dx & ~31);
+       dst_idx = dx % 32;
+       first = 0xffffffffU >> dst_idx;
+       last = ~(0xffffffffU >> ((dst_idx+width) % 32));
+       while (height--) {
+               c = src;
+               p = dst;
+               w = width;
+               if (dst_idx+width <= 32) {
+                       /* Single destination word */
+                       first &= last;
+                       memset(d.pixels, 0, sizeof(d));
+                       memcpy(d.pixels+dst_idx, c, width);
+                       c += width;
+                       c2p_32x8(d.words);
+                       store_planar_masked(p, dst_nextplane, bpp, d.words,
+                                           first);
+                       p += 4;
+               } else {
+                       /* Multiple destination words */
+                       w = width;
+                       /* Leading bits */
+                       if (dst_idx) {
+                               w = 32 - dst_idx;
+                               memset(d.pixels, 0, dst_idx);
+                               memcpy(d.pixels+dst_idx, c, w);
+                               c += w;
+                               c2p_32x8(d.words);
+                               store_planar_masked(p, dst_nextplane, bpp,
+                                                   d.words, first);
+                               p += 4;
+                               w = width-w;
+                       }
+                       /* Main chunk */
+                       while (w >= 32) {
+                               memcpy(d.pixels, c, 32);
+                               c += 32;
+                               c2p_32x8(d.words);
+                               store_planar(p, dst_nextplane, bpp, d.words);
+                               p += 4;
+                               w -= 32;
+                       }
+                       /* Trailing bits */
+                       w %= 32;
+                       if (w > 0) {
+                               memcpy(d.pixels, c, w);
+                               memset(d.pixels+w, 0, 32-w);
+                               c2p_32x8(d.words);
+                               store_planar_masked(p, dst_nextplane, bpp,
+                                                   d.words, last);
+                       }
+               }
+               src += src_nextline;
+               dst += dst_nextline;
+       }
+}
+EXPORT_SYMBOL_GPL(c2p_planar);
+
+MODULE_LICENSE("GPL");
index 4bcff81b50e03afa91f6dbf8eeef0784a2f12f12..1657b9608b040d6b1a1dd0927a6e9cf6ba768f55 100644 (file)
 #include <asm/fb.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#ifdef CONFIG_ATARI
-#include <asm/atariints.h>
-#endif
-#if defined(__mc68000__)
-#include <asm/machdep.h>
-#include <asm/setup.h>
-#endif
 
 #include "fbcon.h"
 
@@ -155,9 +148,6 @@ static int fbcon_set_origin(struct vc_data *);
 
 #define CURSOR_DRAW_DELAY              (1)
 
-/* # VBL ints between cursor state changes */
-#define ATARI_CURSOR_BLINK_RATE                (42)
-
 static int vbl_cursor_cnt;
 static int fbcon_cursor_noblink;
 
@@ -403,20 +393,6 @@ static void fb_flashcursor(struct work_struct *work)
        release_console_sem();
 }
 
-#ifdef CONFIG_ATARI
-static int cursor_blink_rate;
-static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
-{
-       struct fb_info *info = dev_id;
-
-       if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
-               schedule_work(&info->queue);    
-               vbl_cursor_cnt = cursor_blink_rate; 
-       }
-       return IRQ_HANDLED;
-}
-#endif
-       
 static void cursor_timer_handler(unsigned long dev_addr)
 {
        struct fb_info *info = (struct fb_info *) dev_addr;
@@ -1017,15 +993,6 @@ static const char *fbcon_startup(void)
                info->var.yres,
                info->var.bits_per_pixel);
 
-#ifdef CONFIG_ATARI
-       if (MACH_IS_ATARI) {
-               cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
-               (void)request_irq(IRQ_AUTO_4, fb_vbl_handler,
-                               IRQ_TYPE_PRIO, "framebuffer vbl",
-                               info);
-       }
-#endif /* CONFIG_ATARI */
-
        fbcon_add_cursor_timer(info);
        fbcon_has_exited = 0;
        return display_desc;
@@ -3454,11 +3421,6 @@ static void fbcon_exit(void)
        if (fbcon_has_exited)
                return;
 
-#ifdef CONFIG_ATARI
-       if (MACH_IS_ATARI)
-               free_irq(IRQ_AUTO_4, fb_vbl_handler);
-#endif
-
        kfree((void *)softback_buf);
        softback_buf = 0UL;
 
index ec68c741b5645eddd206df2a02b492b3ee783650..3efa12f9ee50e0babdc50439069dc6126b7da1d0 100644 (file)
@@ -770,6 +770,12 @@ config TXX9_WDT
 
 # POWERPC Architecture
 
+config GEF_WDT
+       tristate "GE Fanuc Watchdog Timer"
+       depends on GEF_SBC610
+       ---help---
+         Watchdog timer found in a number of GE Fanuc single board computers.
+
 config MPC5200_WDT
        tristate "MPC5200 Watchdog Timer"
        depends on PPC_MPC52xx
@@ -790,6 +796,14 @@ config MV64X60_WDT
        tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
        depends on MV64X60
 
+config PIKA_WDT
+       tristate "PIKA FPGA Watchdog"
+       depends on WARP
+       default y
+       help
+         This enables the watchdog in the PIKA FPGA. Currently used on
+         the Warp platform.
+
 config BOOKE_WDT
        bool "PowerPC Book-E Watchdog Timer"
        depends on BOOKE || 4xx
index c19b866f5ed1d6a8e73cc627f494baadf0468af1..806b3eb085366a057887c0863936c27b53266d29 100644 (file)
@@ -111,9 +111,11 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 # PARISC Architecture
 
 # POWERPC Architecture
+obj-$(CONFIG_GEF_WDT) += gef_wdt.o
 obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
 obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o
 obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_PIKA_WDT) += pika_wdt.o
 obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
 
 # PPC64 Architecture
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
new file mode 100644 (file)
index 0000000..f0c2b7a
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * GE Fanuc watchdog userspace interface
+ *
+ * Author:  Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Based on: mv64x60_wdt.c (MV64X60 watchdog userspace interface)
+ *   Author: James Chapman <jchapman@katalix.com>
+ */
+
+/* TODO:
+ * This driver does not provide support for the hardwares capability of sending
+ * an interrupt at a programmable threshold.
+ *
+ * This driver currently can only support 1 watchdog - there are 2 in the
+ * hardware that this driver supports. Thus one could be configured as a
+ * process-based watchdog (via /dev/watchdog), the second (using the interrupt
+ * capabilities) a kernel-based watchdog.
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <sysdev/fsl_soc.h>
+
+/*
+ * The watchdog configuration register contains a pair of 2-bit fields,
+ *   1.  a reload field, bits 27-26, which triggers a reload of
+ *       the countdown register, and
+ *   2.  an enable field, bits 25-24, which toggles between
+ *       enabling and disabling the watchdog timer.
+ * Bit 31 is a read-only field which indicates whether the
+ * watchdog timer is currently enabled.
+ *
+ * The low 24 bits contain the timer reload value.
+ */
+#define GEF_WDC_ENABLE_SHIFT   24
+#define GEF_WDC_SERVICE_SHIFT  26
+#define GEF_WDC_ENABLED_SHIFT  31
+
+#define GEF_WDC_ENABLED_TRUE   1
+#define GEF_WDC_ENABLED_FALSE  0
+
+/* Flags bits */
+#define GEF_WDOG_FLAG_OPENED   0
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *gef_wdt_regs;
+static int gef_wdt_timeout;
+static int gef_wdt_count;
+static unsigned int bus_clk;
+static char expect_close;
+static DEFINE_SPINLOCK(gef_wdt_spinlock);
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+       __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static int gef_wdt_toggle_wdc(int enabled_predicate, int field_shift)
+{
+       u32 data;
+       u32 enabled;
+       int ret = 0;
+
+       spin_lock(&gef_wdt_spinlock);
+       data = ioread32be(gef_wdt_regs);
+       enabled = (data >> GEF_WDC_ENABLED_SHIFT) & 1;
+
+       /* only toggle the requested field if enabled state matches predicate */
+       if ((enabled ^ enabled_predicate) == 0) {
+               /* We write a 1, then a 2 -- to the appropriate field */
+               data = (1 << field_shift) | gef_wdt_count;
+               iowrite32be(data, gef_wdt_regs);
+
+               data = (2 << field_shift) | gef_wdt_count;
+               iowrite32be(data, gef_wdt_regs);
+               ret = 1;
+       }
+       spin_unlock(&gef_wdt_spinlock);
+
+       return ret;
+}
+
+static void gef_wdt_service(void)
+{
+       gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
+               GEF_WDC_SERVICE_SHIFT);
+}
+
+static void gef_wdt_handler_enable(void)
+{
+       if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_FALSE,
+                                  GEF_WDC_ENABLE_SHIFT)) {
+               gef_wdt_service();
+               printk(KERN_NOTICE "gef_wdt: watchdog activated\n");
+       }
+}
+
+static void gef_wdt_handler_disable(void)
+{
+       if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
+                                  GEF_WDC_ENABLE_SHIFT))
+               printk(KERN_NOTICE "gef_wdt: watchdog deactivated\n");
+}
+
+static void gef_wdt_set_timeout(unsigned int timeout)
+{
+       /* maximum bus cycle count is 0xFFFFFFFF */
+       if (timeout > 0xFFFFFFFF / bus_clk)
+               timeout = 0xFFFFFFFF / bus_clk;
+
+       /* Register only holds upper 24 bits, bit shifted into lower 24 */
+       gef_wdt_count = (timeout * bus_clk) >> 8;
+       gef_wdt_timeout = timeout;
+}
+
+
+static ssize_t gef_wdt_write(struct file *file, const char __user *data,
+                                size_t len, loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       expect_close = 0;
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               gef_wdt_service();
+       }
+
+       return len;
+}
+
+static long gef_wdt_ioctl(struct file *file, unsigned int cmd,
+                                                       unsigned long arg)
+{
+       int timeout;
+       int options;
+       void __user *argp = (void __user *)arg;
+       static struct watchdog_info info = {
+               .options =      WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
+                               WDIOF_KEEPALIVEPING,
+               .firmware_version = 0,
+               .identity = "GE Fanuc watchdog",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &info, sizeof(info)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(wdt_status, (int __user *)argp))
+                       return -EFAULT;
+               wdt_status &= ~WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_SETOPTIONS:
+               if (get_user(options, (int __user *)argp))
+                       return -EFAULT;
+
+               if (options & WDIOS_DISABLECARD)
+                       gef_wdt_handler_disable();
+
+               if (options & WDIOS_ENABLECARD)
+                       gef_wdt_handler_enable();
+               break;
+
+       case WDIOC_KEEPALIVE:
+               gef_wdt_service();
+               wdt_status |= WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(timeout, (int __user *)argp))
+                       return -EFAULT;
+               gef_wdt_set_timeout(timeout);
+               /* Fall through */
+
+       case WDIOC_GETTIMEOUT:
+               if (put_user(gef_wdt_timeout, (int __user *)argp))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static int gef_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(GEF_WDOG_FLAG_OPENED, &wdt_flags))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       gef_wdt_handler_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int gef_wdt_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42)
+               gef_wdt_handler_disable();
+       else {
+               printk(KERN_CRIT
+                      "gef_wdt: unexpected close, not stopping timer!\n");
+               gef_wdt_service();
+       }
+       expect_close = 0;
+
+       clear_bit(GEF_WDOG_FLAG_OPENED, &wdt_flags);
+
+       return 0;
+}
+
+static const struct file_operations gef_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = gef_wdt_write,
+       .unlocked_ioctl = gef_wdt_ioctl,
+       .open = gef_wdt_open,
+       .release = gef_wdt_release,
+};
+
+static struct miscdevice gef_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &gef_wdt_fops,
+};
+
+
+static int __devinit gef_wdt_probe(struct of_device *dev,
+       const struct of_device_id *match)
+{
+       int timeout = 10;
+       u32 freq;
+
+       bus_clk = 133; /* in MHz */
+
+       freq = fsl_get_sys_freq();
+       if (freq > 0)
+               bus_clk = freq;
+
+       /* Map devices registers into memory */
+       gef_wdt_regs = of_iomap(dev->node, 0);
+       if (gef_wdt_regs == NULL)
+               return -ENOMEM;
+
+       gef_wdt_set_timeout(timeout);
+
+       gef_wdt_handler_disable();      /* in case timer was already running */
+
+       return misc_register(&gef_wdt_miscdev);
+}
+
+static int __devexit gef_wdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&gef_wdt_miscdev);
+
+       gef_wdt_handler_disable();
+
+       iounmap(gef_wdt_regs);
+
+       return 0;
+}
+
+static const struct of_device_id gef_wdt_ids[] = {
+       {
+               .compatible = "gef,fpga-wdt",
+       },
+       {},
+};
+
+static struct of_platform_driver gef_wdt_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "gef_wdt",
+       .match_table    = gef_wdt_ids,
+       .probe          = gef_wdt_probe,
+};
+
+static int __init gef_wdt_init(void)
+{
+       printk(KERN_INFO "GE Fanuc watchdog driver\n");
+       return of_register_platform_driver(&gef_wdt_driver);
+}
+
+static void __exit gef_wdt_exit(void)
+{
+       of_unregister_platform_driver(&gef_wdt_driver);
+}
+
+module_init(gef_wdt_init);
+module_exit(gef_wdt_exit);
+
+MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>");
+MODULE_DESCRIPTION("GE Fanuc watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform: gef_wdt");
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c
new file mode 100644 (file)
index 0000000..2d22e99
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * PIKA FPGA based Watchdog Timer
+ *
+ * Copyright (c) 2008 PIKA Technologies
+ *   Sean MacLennan <smaclennan@pikatech.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+#define DRV_NAME "PIKA-WDT"
+#define PFX DRV_NAME ": "
+
+/* Hardware timeout in seconds */
+#define WDT_HW_TIMEOUT 2
+
+/* Timer heartbeat (500ms) */
+#define WDT_TIMEOUT    (HZ/2)
+
+/* User land timeout */
+#define WDT_HEARTBEAT 15
+static int heartbeat = WDT_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
+       "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+       "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static struct {
+       void __iomem *fpga;
+       unsigned long next_heartbeat;   /* the next_heartbeat for the timer */
+       unsigned long open;
+       char expect_close;
+       int bootstatus;
+       struct timer_list timer;        /* The timer that pings the watchdog */
+} pikawdt_private;
+
+static struct watchdog_info ident = {
+       .identity       = DRV_NAME,
+       .options        = WDIOF_CARDRESET |
+                         WDIOF_SETTIMEOUT |
+                         WDIOF_KEEPALIVEPING |
+                         WDIOF_MAGICCLOSE,
+};
+
+/*
+ * Reload the watchdog timer.  (ie, pat the watchdog)
+ */
+static inline void pikawdt_reset(void)
+{
+       /* -- FPGA: Reset Control Register (32bit R/W) (Offset: 0x14) --
+        * Bit 7,    WTCHDG_EN: When set to 1, the watchdog timer is enabled.
+        *           Once enabled, it cannot be disabled. The watchdog can be
+        *           kicked by performing any write access to the reset
+        *           control register (this register).
+        * Bit 8-11, WTCHDG_TIMEOUT_SEC: Sets the watchdog timeout value in
+        *           seconds. Valid ranges are 1 to 15 seconds. The value can
+        *           be modified dynamically.
+        */
+       unsigned reset = in_be32(pikawdt_private.fpga + 0x14);
+       /* enable with max timeout - 15 seconds */
+       reset |= (1 << 7) + (WDT_HW_TIMEOUT << 8);
+       out_be32(pikawdt_private.fpga + 0x14, reset);
+}
+
+/*
+ * Timer tick
+ */
+static void pikawdt_ping(unsigned long data)
+{
+       if (time_before(jiffies, pikawdt_private.next_heartbeat) ||
+                       (!nowayout && !pikawdt_private.open)) {
+               pikawdt_reset();
+               mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
+       } else
+               printk(KERN_CRIT PFX "I will reset your machine !\n");
+}
+
+
+static void pikawdt_keepalive(void)
+{
+       pikawdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+}
+
+static void pikawdt_start(void)
+{
+       pikawdt_keepalive();
+       mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int pikawdt_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+       if (test_and_set_bit(0, &pikawdt_private.open))
+               return -EBUSY;
+
+       pikawdt_start();
+
+       return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ */
+static int pikawdt_release(struct inode *inode, struct file *file)
+{
+       /* stop internal ping */
+       if (!pikawdt_private.expect_close)
+               del_timer(&pikawdt_private.timer);
+
+       clear_bit(0, &pikawdt_private.open);
+       pikawdt_private.expect_close = 0;
+       return 0;
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t pikawdt_write(struct file *file, const char __user *data,
+                            size_t len, loff_t *ppos)
+{
+       if (!len)
+               return 0;
+
+       /* Scan for magic character */
+       if (!nowayout) {
+               size_t i;
+
+               pikawdt_private.expect_close = 0;
+
+               for (i = 0; i < len; i++) {
+                       char c;
+                       if (get_user(c, data + i))
+                               return -EFAULT;
+                       if (c == 'V') {
+                               pikawdt_private.expect_close = 42;
+                               break;
+                       }
+               }
+       }
+
+       pikawdt_keepalive();
+
+       return len;
+}
+
+/*
+ * Handle commands from user-space.
+ */
+static long pikawdt_ioctl(struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_value;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+       case WDIOC_GETSTATUS:
+               return put_user(0, p);
+
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(pikawdt_private.bootstatus, p);
+
+       case WDIOC_KEEPALIVE:
+               pikawdt_keepalive();
+               return 0;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_value, p))
+                       return -EFAULT;
+
+               heartbeat = new_value;
+               pikawdt_keepalive();
+
+               return put_user(new_value, p);  /* return current value */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(heartbeat, p);
+       }
+       return -ENOTTY;
+}
+
+
+static const struct file_operations pikawdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .open           = pikawdt_open,
+       .release        = pikawdt_release,
+       .write          = pikawdt_write,
+       .unlocked_ioctl = pikawdt_ioctl,
+};
+
+static struct miscdevice pikawdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &pikawdt_fops,
+};
+
+static int __init pikawdt_init(void)
+{
+       struct device_node *np;
+       void __iomem *fpga;
+       static u32 post1;
+       int ret;
+
+       np = of_find_compatible_node(NULL, NULL, "pika,fpga");
+       if (np == NULL) {
+               printk(KERN_ERR PFX "Unable to find fpga.\n");
+               return -ENOENT;
+       }
+
+       pikawdt_private.fpga = of_iomap(np, 0);
+       of_node_put(np);
+       if (pikawdt_private.fpga == NULL) {
+               printk(KERN_ERR PFX "Unable to map fpga.\n");
+               return -ENOMEM;
+       }
+
+       ident.firmware_version = in_be32(pikawdt_private.fpga + 0x1c) & 0xffff;
+
+       /* POST information is in the sd area. */
+       np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
+       if (np == NULL) {
+               printk(KERN_ERR PFX "Unable to find fpga-sd.\n");
+               ret = -ENOENT;
+               goto out;
+       }
+
+       fpga = of_iomap(np, 0);
+       of_node_put(np);
+       if (fpga == NULL) {
+               printk(KERN_ERR PFX "Unable to map fpga-sd.\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* -- FPGA: POST Test Results Register 1 (32bit R/W) (Offset: 0x4040) --
+        * Bit 31,   WDOG: Set to 1 when the last reset was caused by a watchdog
+        *           timeout.
+        */
+       post1 = in_be32(fpga + 0x40);
+       if (post1 & 0x80000000)
+               pikawdt_private.bootstatus = WDIOF_CARDRESET;
+
+       iounmap(fpga);
+
+       setup_timer(&pikawdt_private.timer, pikawdt_ping, 0);
+
+       ret = misc_register(&pikawdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR PFX "Unable to register miscdev.\n");
+               goto out;
+       }
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+                                                       heartbeat, nowayout);
+       return 0;
+
+out:
+       iounmap(pikawdt_private.fpga);
+       return ret;
+}
+
+static void __exit pikawdt_exit(void)
+{
+       misc_deregister(&pikawdt_miscdev);
+
+       iounmap(pikawdt_private.fpga);
+}
+
+module_init(pikawdt_init);
+module_exit(pikawdt_exit);
+
+MODULE_AUTHOR("Sean MacLennan <smaclennan@pikatech.com>");
+MODULE_DESCRIPTION("PIKA FPGA based Watchdog Timer");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
index 2bc0d4d4b415d35b352febb6e6a1cf39f884faa5..a2d2e8eb228298cb7a698582c154868540c558fe 100644 (file)
@@ -279,7 +279,7 @@ static struct miscdevice wm8350_wdt_miscdev = {
        .fops = &wm8350_wdt_fops,
 };
 
-static int wm8350_wdt_probe(struct platform_device *pdev)
+static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
 {
        struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 
@@ -296,7 +296,7 @@ static int wm8350_wdt_probe(struct platform_device *pdev)
        return misc_register(&wm8350_wdt_miscdev);
 }
 
-static int __exit wm8350_wdt_remove(struct platform_device *pdev)
+static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
 {
        misc_deregister(&wm8350_wdt_miscdev);
 
@@ -305,7 +305,7 @@ static int __exit wm8350_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8350_wdt_driver = {
        .probe = wm8350_wdt_probe,
-       .remove = wm8350_wdt_remove,
+       .remove = __devexit_p(wm8350_wdt_remove),
        .driver = {
                .name = "wm8350-wdt",
        },
diff --git a/drivers/zorro/.gitignore b/drivers/zorro/.gitignore
new file mode 100644 (file)
index 0000000..34f980b
--- /dev/null
@@ -0,0 +1,2 @@
+devlist.h
+gen-devlist
index 5290552d2ef7e0525f12f6fecfdbecd756088e7e..1d2a772ea14c017419a145ec3a8be582336cda97 100644 (file)
@@ -77,17 +77,21 @@ static struct bin_attribute zorro_config_attr = {
        .read = zorro_read_config,
 };
 
-void zorro_create_sysfs_dev_files(struct zorro_dev *z)
+int zorro_create_sysfs_dev_files(struct zorro_dev *z)
 {
        struct device *dev = &z->dev;
+       int error;
 
        /* current configuration's attributes */
-       device_create_file(dev, &dev_attr_id);
-       device_create_file(dev, &dev_attr_type);
-       device_create_file(dev, &dev_attr_serial);
-       device_create_file(dev, &dev_attr_slotaddr);
-       device_create_file(dev, &dev_attr_slotsize);
-       device_create_file(dev, &dev_attr_resource);
-       sysfs_create_bin_file(&dev->kobj, &zorro_config_attr);
+       if ((error = device_create_file(dev, &dev_attr_id)) ||
+           (error = device_create_file(dev, &dev_attr_type)) ||
+           (error = device_create_file(dev, &dev_attr_serial)) ||
+           (error = device_create_file(dev, &dev_attr_slotaddr)) ||
+           (error = device_create_file(dev, &dev_attr_slotsize)) ||
+           (error = device_create_file(dev, &dev_attr_resource)) ||
+           (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr)))
+               return error;
+
+       return 0;
 }
 
index dff16d9767d86a740a1ad8da9563ec09c9902688..a1585d6f6486e8e7165a87f4ca6811a7ec57f10c 100644 (file)
@@ -130,6 +130,7 @@ static int __init zorro_init(void)
 {
     struct zorro_dev *z;
     unsigned int i;
+    int error;
 
     if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
        return 0;
@@ -140,7 +141,11 @@ static int __init zorro_init(void)
     /* Initialize the Zorro bus */
     INIT_LIST_HEAD(&zorro_bus.devices);
     strcpy(zorro_bus.dev.bus_id, "zorro");
-    device_register(&zorro_bus.dev);
+    error = device_register(&zorro_bus.dev);
+    if (error) {
+       pr_err("Zorro: Error registering zorro_bus\n");
+       return error;
+    }
 
     /* Request the resources */
     zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
@@ -160,15 +165,19 @@ static int __init zorro_init(void)
        zorro_name_device(z);
        z->resource.name = z->name;
        if (request_resource(zorro_find_parent_resource(z), &z->resource))
-           printk(KERN_ERR "Zorro: Address space collision on device %s "
-                  "[%lx:%lx]\n",
-                  z->name, (unsigned long)zorro_resource_start(z),
-                  (unsigned long)zorro_resource_end(z));
+           pr_err("Zorro: Address space collision on device %s %pR\n",
+                  z->name, &z->resource);
        sprintf(z->dev.bus_id, "%02x", i);
        z->dev.parent = &zorro_bus.dev;
        z->dev.bus = &zorro_bus_type;
-       device_register(&z->dev);
-       zorro_create_sysfs_dev_files(z);
+       error = device_register(&z->dev);
+       if (error) {
+           pr_err("Zorro: Error registering device %s\n", z->name);
+           continue;
+       }
+       error = zorro_create_sysfs_dev_files(z);
+       if (error)
+           dev_err(&z->dev, "Error creating sysfs files\n");
     }
 
     /* Mark all available Zorro II memory */
index 5c91adac4df149534636e017d9c19a976ae30f7c..b682d5ccd63f74b1be7aae6db188270318891f14 100644 (file)
@@ -1,4 +1,4 @@
 
 extern void zorro_name_device(struct zorro_dev *z);
-extern void zorro_create_sysfs_dev_files(struct zorro_dev *z);
+extern int zorro_create_sysfs_dev_files(struct zorro_dev *z);
 
index 2f107d1a6a45937efe327eebf31b8cf0bc1c5aa5..1d1d27442235b9487c3db8a8490a6a0da7c6122c 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -25,19 +25,6 @@ static struct mutex debug_buf_lock;
 
 static struct dentry *dlm_root;
 
-struct rsb_iter {
-       int entry;
-       int format;
-       int header;
-       struct dlm_ls *ls;
-       struct list_head *next;
-       struct dlm_rsb *rsb;
-};
-
-/*
- * dump all rsb's in the lockspace hash table
- */
-
 static char *print_lockmode(int mode)
 {
        switch (mode) {
@@ -60,13 +47,13 @@ static char *print_lockmode(int mode)
        }
 }
 
-static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              struct dlm_rsb *res)
+static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             struct dlm_rsb *res)
 {
        seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
 
-       if (lkb->lkb_status == DLM_LKSTS_CONVERT
-           || lkb->lkb_status == DLM_LKSTS_WAITING)
+       if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
+           lkb->lkb_status == DLM_LKSTS_WAITING)
                seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
 
        if (lkb->lkb_nodeid) {
@@ -80,33 +67,42 @@ static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
        if (lkb->lkb_wait_type)
                seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
 
-       seq_printf(s, "\n");
+       return seq_printf(s, "\n");
 }
 
 static int print_format1(struct dlm_rsb *res, struct seq_file *s)
 {
        struct dlm_lkb *lkb;
        int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
+       int rv;
 
        lock_rsb(res);
 
-       seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
+       rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
+                       res, res->res_length);
+       if (rv)
+               goto out;
+
        for (i = 0; i < res->res_length; i++) {
                if (isprint(res->res_name[i]))
                        seq_printf(s, "%c", res->res_name[i]);
                else
                        seq_printf(s, "%c", '.');
        }
+
        if (res->res_nodeid > 0)
-               seq_printf(s, "\"  \nLocal Copy, Master is node %d\n",
-                          res->res_nodeid);
+               rv = seq_printf(s, "\"  \nLocal Copy, Master is node %d\n",
+                               res->res_nodeid);
        else if (res->res_nodeid == 0)
-               seq_printf(s, "\"  \nMaster Copy\n");
+               rv = seq_printf(s, "\"  \nMaster Copy\n");
        else if (res->res_nodeid == -1)
-               seq_printf(s, "\"  \nLooking up master (lkid %x)\n",
-                          res->res_first_lkid);
+               rv = seq_printf(s, "\"  \nLooking up master (lkid %x)\n",
+                               res->res_first_lkid);
        else
-               seq_printf(s, "\"  \nInvalid master %d\n", res->res_nodeid);
+               rv = seq_printf(s, "\"  \nInvalid master %d\n",
+                               res->res_nodeid);
+       if (rv)
+               goto out;
 
        /* Print the LVB: */
        if (res->res_lvbptr) {
@@ -119,52 +115,66 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
                }
                if (rsb_flag(res, RSB_VALNOTVALID))
                        seq_printf(s, " (INVALID)");
-               seq_printf(s, "\n");
+               rv = seq_printf(s, "\n");
+               if (rv)
+                       goto out;
        }
 
        root_list = !list_empty(&res->res_root_list);
        recover_list = !list_empty(&res->res_recover_list);
 
        if (root_list || recover_list) {
-               seq_printf(s, "Recovery: root %d recover %d flags %lx "
-                          "count %d\n", root_list, recover_list,
-                          res->res_flags, res->res_recover_locks_count);
+               rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
+                               "count %d\n", root_list, recover_list,
+                               res->res_flags, res->res_recover_locks_count);
+               if (rv)
+                       goto out;
        }
 
        /* Print the locks attached to this resource */
        seq_printf(s, "Granted Queue\n");
-       list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        seq_printf(s, "Conversion Queue\n");
-       list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        seq_printf(s, "Waiting Queue\n");
-       list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        if (list_empty(&res->res_lookup))
                goto out;
 
        seq_printf(s, "Lookup Queue\n");
        list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
-               seq_printf(s, "%08x %s", lkb->lkb_id,
-                          print_lockmode(lkb->lkb_rqmode));
+               rv = seq_printf(s, "%08x %s", lkb->lkb_id,
+                               print_lockmode(lkb->lkb_rqmode));
                if (lkb->lkb_wait_type)
                        seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
-               seq_printf(s, "\n");
+               rv = seq_printf(s, "\n");
        }
  out:
        unlock_rsb(res);
-       return 0;
+       return rv;
 }
 
-static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              struct dlm_rsb *r)
+static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             struct dlm_rsb *r)
 {
        u64 xid = 0;
        u64 us;
+       int rv;
 
        if (lkb->lkb_flags & DLM_IFL_USER) {
                if (lkb->lkb_ua)
@@ -177,69 +187,82 @@ static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
        /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
           r_nodeid r_len r_name */
 
-       seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
-                  lkb->lkb_id,
-                  lkb->lkb_nodeid,
-                  lkb->lkb_remid,
-                  lkb->lkb_ownpid,
-                  (unsigned long long)xid,
-                  lkb->lkb_exflags,
-                  lkb->lkb_flags,
-                  lkb->lkb_status,
-                  lkb->lkb_grmode,
-                  lkb->lkb_rqmode,
-                  (unsigned long long)us,
-                  r->res_nodeid,
-                  r->res_length,
-                  r->res_name);
+       rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
+                       lkb->lkb_id,
+                       lkb->lkb_nodeid,
+                       lkb->lkb_remid,
+                       lkb->lkb_ownpid,
+                       (unsigned long long)xid,
+                       lkb->lkb_exflags,
+                       lkb->lkb_flags,
+                       lkb->lkb_status,
+                       lkb->lkb_grmode,
+                       lkb->lkb_rqmode,
+                       (unsigned long long)us,
+                       r->res_nodeid,
+                       r->res_length,
+                       r->res_name);
+       return rv;
 }
 
 static int print_format2(struct dlm_rsb *r, struct seq_file *s)
 {
        struct dlm_lkb *lkb;
+       int rv = 0;
 
        lock_rsb(r);
 
-       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
-
-       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
+       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
 
-       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
+       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
 
+       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
+ out:
        unlock_rsb(r);
-       return 0;
+       return rv;
 }
 
-static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              int rsb_lookup)
+static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             int rsb_lookup)
 {
        u64 xid = 0;
+       int rv;
 
        if (lkb->lkb_flags & DLM_IFL_USER) {
                if (lkb->lkb_ua)
                        xid = lkb->lkb_ua->xid;
        }
 
-       seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
-                  lkb->lkb_id,
-                  lkb->lkb_nodeid,
-                  lkb->lkb_remid,
-                  lkb->lkb_ownpid,
-                  (unsigned long long)xid,
-                  lkb->lkb_exflags,
-                  lkb->lkb_flags,
-                  lkb->lkb_status,
-                  lkb->lkb_grmode,
-                  lkb->lkb_rqmode,
-                  lkb->lkb_highbast,
-                  rsb_lookup,
-                  lkb->lkb_wait_type,
-                  lkb->lkb_lvbseq,
-                  (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
-                  (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+       rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
+                       lkb->lkb_id,
+                       lkb->lkb_nodeid,
+                       lkb->lkb_remid,
+                       lkb->lkb_ownpid,
+                       (unsigned long long)xid,
+                       lkb->lkb_exflags,
+                       lkb->lkb_flags,
+                       lkb->lkb_status,
+                       lkb->lkb_grmode,
+                       lkb->lkb_rqmode,
+                       lkb->lkb_highbast,
+                       rsb_lookup,
+                       lkb->lkb_wait_type,
+                       lkb->lkb_lvbseq,
+                       (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
+                       (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+       return rv;
 }
 
 static int print_format3(struct dlm_rsb *r, struct seq_file *s)
@@ -247,18 +270,21 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
        struct dlm_lkb *lkb;
        int i, lvblen = r->res_ls->ls_lvblen;
        int print_name = 1;
+       int rv;
 
        lock_rsb(r);
 
-       seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
-                  r,
-                  r->res_nodeid,
-                  r->res_first_lkid,
-                  r->res_flags,
-                  !list_empty(&r->res_root_list),
-                  !list_empty(&r->res_recover_list),
-                  r->res_recover_locks_count,
-                  r->res_length);
+       rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
+                       r,
+                       r->res_nodeid,
+                       r->res_first_lkid,
+                       r->res_flags,
+                       !list_empty(&r->res_root_list),
+                       !list_empty(&r->res_recover_list),
+                       r->res_recover_locks_count,
+                       r->res_length);
+       if (rv)
+               goto out;
 
        for (i = 0; i < r->res_length; i++) {
                if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
@@ -273,7 +299,9 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
                else
                        seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
        }
-       seq_printf(s, "\n");
+       rv = seq_printf(s, "\n");
+       if (rv)
+               goto out;
 
        if (!r->res_lvbptr)
                goto do_locks;
@@ -282,344 +310,294 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
 
        for (i = 0; i < lvblen; i++)
                seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
-       seq_printf(s, "\n");
+       rv = seq_printf(s, "\n");
+       if (rv)
+               goto out;
 
  do_locks:
-       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
-               print_format3_lock(s, lkb, 1);
-
-       unlock_rsb(r);
-       return 0;
-}
-
-static int rsb_iter_next(struct rsb_iter *ri)
-{
-       struct dlm_ls *ls = ri->ls;
-       int i;
-
-       if (!ri->next) {
- top:
-               /* Find the next non-empty hash bucket */
-               for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
-                       read_lock(&ls->ls_rsbtbl[i].lock);
-                       if (!list_empty(&ls->ls_rsbtbl[i].list)) {
-                               ri->next = ls->ls_rsbtbl[i].list.next;
-                               ri->rsb = list_entry(ri->next, struct dlm_rsb,
-                                                       res_hashchain);
-                               dlm_hold_rsb(ri->rsb);
-                               read_unlock(&ls->ls_rsbtbl[i].lock);
-                               break;
-                       }
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
-               }
-               ri->entry = i;
-
-               if (ri->entry >= ls->ls_rsbtbl_size)
-                       return 1;
-       } else {
-               struct dlm_rsb *old = ri->rsb;
-               i = ri->entry;
-               read_lock(&ls->ls_rsbtbl[i].lock);
-               ri->next = ri->next->next;
-               if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
-                       /* End of list - move to next bucket */
-                       ri->next = NULL;
-                       ri->entry++;
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
-                       dlm_put_rsb(old);
-                       goto top;
-               }
-               ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
-               dlm_hold_rsb(ri->rsb);
-               read_unlock(&ls->ls_rsbtbl[i].lock);
-               dlm_put_rsb(old);
+       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return 0;
-}
-
-static void rsb_iter_free(struct rsb_iter *ri)
-{
-       kfree(ri);
-}
-
-static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
-{
-       struct rsb_iter *ri;
-
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
-       if (!ri)
-               return NULL;
-
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 1;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return ri;
-}
-
-static void *rsb_seq_start(struct seq_file *file, loff_t *pos)
-{
-       struct rsb_iter *ri;
-       loff_t n = *pos;
-
-       ri = rsb_iter_init(file->private);
-       if (!ri)
-               return NULL;
-
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
-                       return NULL;
-               }
+       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return ri;
-}
-
-static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos)
-{
-       struct rsb_iter *ri = iter_ptr;
-
-       (*pos)++;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
+               rv = print_format3_lock(s, lkb, 1);
+               if (rv)
+                       goto out;
        }
-
-       return ri;
+ out:
+       unlock_rsb(r);
+       return rv;
 }
 
-static void rsb_seq_stop(struct seq_file *file, void *iter_ptr)
-{
-       /* nothing for now */
-}
+struct rsbtbl_iter {
+       struct dlm_rsb *rsb;
+       unsigned bucket;
+       int format;
+       int header;
+};
 
-static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
+/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
+   If the buffer is full, seq_printf can be called again, but it
+   does nothing and just returns -1.  So, the these printing routines
+   periodically check the return value to avoid wasting too much time
+   trying to print to a full buffer. */
+
+static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsb_iter *ri = iter_ptr;
+       struct rsbtbl_iter *ri = iter_ptr;
+       int rv = 0;
 
        switch (ri->format) {
        case 1:
-               print_format1(ri->rsb, file);
+               rv = print_format1(ri->rsb, seq);
                break;
        case 2:
                if (ri->header) {
-                       seq_printf(file, "id nodeid remid pid xid exflags "
-                                        "flags sts grmode rqmode time_ms "
-                                        "r_nodeid r_len r_name\n");
+                       seq_printf(seq, "id nodeid remid pid xid exflags "
+                                       "flags sts grmode rqmode time_ms "
+                                       "r_nodeid r_len r_name\n");
                        ri->header = 0;
                }
-               print_format2(ri->rsb, file);
+               rv = print_format2(ri->rsb, seq);
                break;
        case 3:
                if (ri->header) {
-                       seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
+                       seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
                        ri->header = 0;
                }
-               print_format3(ri->rsb, file);
+               rv = print_format3(ri->rsb, seq);
                break;
        }
 
-       return 0;
+       return rv;
 }
 
-static struct seq_operations rsb_seq_ops = {
-       .start = rsb_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
-};
+static struct seq_operations format1_seq_ops;
+static struct seq_operations format2_seq_ops;
+static struct seq_operations format3_seq_ops;
 
-static int rsb_open(struct inode *inode, struct file *file)
+static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct seq_file *seq;
-       int ret;
-
-       ret = seq_open(file, &rsb_seq_ops);
-       if (ret)
-               return ret;
-
-       seq = file->private_data;
-       seq->private = inode->i_private;
-
-       return 0;
-}
-
-static const struct file_operations rsb_fops = {
-       .owner   = THIS_MODULE,
-       .open    = rsb_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release
-};
+       struct dlm_ls *ls = seq->private;
+       struct rsbtbl_iter *ri;
+       struct dlm_rsb *r;
+       loff_t n = *pos;
+       unsigned bucket, entry;
 
-/*
- * Dump state in compact per-lock listing
- */
+       bucket = n >> 32;
+       entry = n & ((1LL << 32) - 1);
 
-static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
-{
-       struct rsb_iter *ri;
+       if (bucket >= ls->ls_rsbtbl_size)
+               return NULL;
 
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
+       ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
        if (!ri)
                return NULL;
-
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 2;
-
-       if (*pos == 0)
+       if (n == 0)
                ri->header = 1;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       if (seq->op == &format1_seq_ops)
+               ri->format = 1;
+       if (seq->op == &format2_seq_ops)
+               ri->format = 2;
+       if (seq->op == &format3_seq_ops)
+               ri->format = 3;
+
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
+       if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+               list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
+                                   res_hashchain) {
+                       if (!entry--) {
+                               dlm_hold_rsb(r);
+                               ri->rsb = r;
+                               ri->bucket = bucket;
+                               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                               return ri;
+                       }
+               }
        }
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 
-       return ri;
-}
+       /*
+        * move to the first rsb in the next non-empty bucket
+        */
 
-static void *locks_seq_start(struct seq_file *file, loff_t *pos)
-{
-       struct rsb_iter *ri;
-       loff_t n = *pos;
+       /* zero the entry */
+       n &= ~((1LL << 32) - 1);
 
-       ri = locks_iter_init(file->private, pos);
-       if (!ri)
-               return NULL;
+       while (1) {
+               bucket++;
+               n += 1LL << 32;
 
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
+               if (bucket >= ls->ls_rsbtbl_size) {
+                       kfree(ri);
                        return NULL;
                }
-       }
 
-       return ri;
+               spin_lock(&ls->ls_rsbtbl[bucket].lock);
+               if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+                       r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
+                                            struct dlm_rsb, res_hashchain);
+                       dlm_hold_rsb(r);
+                       ri->rsb = r;
+                       ri->bucket = bucket;
+                       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                       *pos = n;
+                       return ri;
+               }
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+       }
 }
 
-static struct seq_operations locks_seq_ops = {
-       .start = locks_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
-};
-
-static int locks_open(struct inode *inode, struct file *file)
+static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 {
-       struct seq_file *seq;
-       int ret;
-
-       ret = seq_open(file, &locks_seq_ops);
-       if (ret)
-               return ret;
-
-       seq = file->private_data;
-       seq->private = inode->i_private;
-
-       return 0;
-}
-
-static const struct file_operations locks_fops = {
-       .owner   = THIS_MODULE,
-       .open    = locks_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release
-};
-
-/*
- * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
- * This can replace both formats 1 and 2 eventually.
- */
+       struct dlm_ls *ls = seq->private;
+       struct rsbtbl_iter *ri = iter_ptr;
+       struct list_head *next;
+       struct dlm_rsb *r, *rp;
+       loff_t n = *pos;
+       unsigned bucket;
+
+       bucket = n >> 32;
+
+       /*
+        * move to the next rsb in the same bucket
+        */
+
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
+       rp = ri->rsb;
+       next = rp->res_hashchain.next;
+
+       if (next != &ls->ls_rsbtbl[bucket].list) {
+               r = list_entry(next, struct dlm_rsb, res_hashchain);
+               dlm_hold_rsb(r);
+               ri->rsb = r;
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+               dlm_put_rsb(rp);
+               ++*pos;
+               return ri;
+       }
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+       dlm_put_rsb(rp);
 
-static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
-{
-       struct rsb_iter *ri;
+       /*
+        * move to the first rsb in the next non-empty bucket
+        */
 
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
-       if (!ri)
-               return NULL;
+       /* zero the entry */
+       n &= ~((1LL << 32) - 1);
 
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 3;
+       while (1) {
+               bucket++;
+               n += 1LL << 32;
 
-       if (*pos == 0)
-               ri->header = 1;
+               if (bucket >= ls->ls_rsbtbl_size) {
+                       kfree(ri);
+                       return NULL;
+               }
 
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+               spin_lock(&ls->ls_rsbtbl[bucket].lock);
+               if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+                       r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
+                                            struct dlm_rsb, res_hashchain);
+                       dlm_hold_rsb(r);
+                       ri->rsb = r;
+                       ri->bucket = bucket;
+                       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                       *pos = n;
+                       return ri;
+               }
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        }
-
-       return ri;
 }
 
-static void *all_seq_start(struct seq_file *file, loff_t *pos)
+static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsb_iter *ri;
-       loff_t n = *pos;
-
-       ri = all_iter_init(file->private, pos);
-       if (!ri)
-               return NULL;
+       struct rsbtbl_iter *ri = iter_ptr;
 
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
-                       return NULL;
-               }
+       if (ri) {
+               dlm_put_rsb(ri->rsb);
+               kfree(ri);
        }
-
-       return ri;
 }
 
-static struct seq_operations all_seq_ops = {
-       .start = all_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
+static struct seq_operations format1_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
 };
 
-static int all_open(struct inode *inode, struct file *file)
+static struct seq_operations format2_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
+};
+
+static struct seq_operations format3_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
+};
+
+static const struct file_operations format1_fops;
+static const struct file_operations format2_fops;
+static const struct file_operations format3_fops;
+
+static int table_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
-       int ret;
+       int ret = -1;
+
+       if (file->f_op == &format1_fops)
+               ret = seq_open(file, &format1_seq_ops);
+       else if (file->f_op == &format2_fops)
+               ret = seq_open(file, &format2_seq_ops);
+       else if (file->f_op == &format3_fops)
+               ret = seq_open(file, &format3_seq_ops);
 
-       ret = seq_open(file, &all_seq_ops);
        if (ret)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->i_private;
-
+       seq->private = inode->i_private; /* the dlm_ls */
        return 0;
 }
 
-static const struct file_operations all_fops = {
+static const struct file_operations format1_fops = {
+       .owner   = THIS_MODULE,
+       .open    = table_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+static const struct file_operations format2_fops = {
+       .owner   = THIS_MODULE,
+       .open    = table_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+static const struct file_operations format3_fops = {
        .owner   = THIS_MODULE,
-       .open    = all_open,
+       .open    = table_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
        .release = seq_release
@@ -689,7 +667,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                      S_IFREG | S_IRUGO,
                                                      dlm_root,
                                                      ls,
-                                                     &rsb_fops);
+                                                     &format1_fops);
        if (!ls->ls_debug_rsb_dentry)
                goto fail;
 
@@ -702,7 +680,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                        S_IFREG | S_IRUGO,
                                                        dlm_root,
                                                        ls,
-                                                       &locks_fops);
+                                                       &format2_fops);
        if (!ls->ls_debug_locks_dentry)
                goto fail;
 
@@ -715,7 +693,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                      S_IFREG | S_IRUGO,
                                                      dlm_root,
                                                      ls,
-                                                     &all_fops);
+                                                     &format3_fops);
        if (!ls->ls_debug_all_dentry)
                goto fail;
 
index ef2f1e353966d85ef15d9a9dd0cf8b273df51f4b..076e86f38bc84a4a6e247b7fb184658592e7f732 100644 (file)
@@ -105,7 +105,7 @@ struct dlm_dirtable {
 struct dlm_rsbtable {
        struct list_head        list;
        struct list_head        toss;
-       rwlock_t                lock;
+       spinlock_t              lock;
 };
 
 struct dlm_lkbtable {
index 6cfe65bbf4a2e16daaf1aec41638430174b407db..01e7d39c5fba8d55a4fa1a4bd8f64e13d4c32a95 100644 (file)
@@ -412,9 +412,9 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
                      unsigned int flags, struct dlm_rsb **r_ret)
 {
        int error;
-       write_lock(&ls->ls_rsbtbl[b].lock);
+       spin_lock(&ls->ls_rsbtbl[b].lock);
        error = _search_rsb(ls, name, len, b, flags, r_ret);
-       write_unlock(&ls->ls_rsbtbl[b].lock);
+       spin_unlock(&ls->ls_rsbtbl[b].lock);
        return error;
 }
 
@@ -478,16 +478,16 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
                r->res_nodeid = nodeid;
        }
 
-       write_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        error = _search_rsb(ls, name, namelen, bucket, 0, &tmp);
        if (!error) {
-               write_unlock(&ls->ls_rsbtbl[bucket].lock);
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
                dlm_free_rsb(r);
                r = tmp;
                goto out;
        }
        list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list);
-       write_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        error = 0;
  out:
        *r_ret = r;
@@ -530,9 +530,9 @@ static void put_rsb(struct dlm_rsb *r)
        struct dlm_ls *ls = r->res_ls;
        uint32_t bucket = r->res_bucket;
 
-       write_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        kref_put(&r->res_ref, toss_rsb);
-       write_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 }
 
 void dlm_put_rsb(struct dlm_rsb *r)
@@ -967,7 +967,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
 
        for (;;) {
                found = 0;
-               write_lock(&ls->ls_rsbtbl[b].lock);
+               spin_lock(&ls->ls_rsbtbl[b].lock);
                list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss,
                                            res_hashchain) {
                        if (!time_after_eq(jiffies, r->res_toss_time +
@@ -978,20 +978,20 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
                }
 
                if (!found) {
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
                        break;
                }
 
                if (kref_put(&r->res_ref, kill_rsb)) {
                        list_del(&r->res_hashchain);
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
 
                        if (is_master(r))
                                dir_remove(r);
                        dlm_free_rsb(r);
                        count++;
                } else {
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
                        log_error(ls, "tossed rsb in use %s", r->res_name);
                }
        }
@@ -4224,7 +4224,7 @@ static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
 {
        struct dlm_rsb *r, *r_ret = NULL;
 
-       read_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, res_hashchain) {
                if (!rsb_flag(r, RSB_LOCKS_PURGED))
                        continue;
@@ -4233,7 +4233,7 @@ static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
                r_ret = r;
                break;
        }
-       read_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        return r_ret;
 }
 
index 8d86b7960f0df7527fed5494230676b137b4f63b..aa32e5f02493656ef461099a024337793437e245 100644 (file)
@@ -464,7 +464,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
        for (i = 0; i < size; i++) {
                INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
                INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
-               rwlock_init(&ls->ls_rsbtbl[i].lock);
+               spin_lock_init(&ls->ls_rsbtbl[i].lock);
        }
 
        size = dlm_config.ci_lkbtbl_size;
index 80aba5bdd4a4b72b0949fe4f0516c02f7d7f25ad..eda43f3626169ec9b08ad03fdecfd9b5aef7e821 100644 (file)
@@ -726,7 +726,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
        }
 
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               read_lock(&ls->ls_rsbtbl[i].lock);
+               spin_lock(&ls->ls_rsbtbl[i].lock);
                list_for_each_entry(r, &ls->ls_rsbtbl[i].list, res_hashchain) {
                        list_add(&r->res_root_list, &ls->ls_root_list);
                        dlm_hold_rsb(r);
@@ -737,7 +737,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
                   but no other recovery steps should do anything with them. */
 
                if (dlm_no_directory(ls)) {
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
+                       spin_unlock(&ls->ls_rsbtbl[i].lock);
                        continue;
                }
 
@@ -745,7 +745,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
                        list_add(&r->res_root_list, &ls->ls_root_list);
                        dlm_hold_rsb(r);
                }
-               read_unlock(&ls->ls_rsbtbl[i].lock);
+               spin_unlock(&ls->ls_rsbtbl[i].lock);
        }
  out:
        up_write(&ls->ls_root_sem);
@@ -775,7 +775,7 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
        int i;
 
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               write_lock(&ls->ls_rsbtbl[i].lock);
+               spin_lock(&ls->ls_rsbtbl[i].lock);
                list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss,
                                         res_hashchain) {
                        if (dlm_no_directory(ls) || !is_master(r)) {
@@ -783,7 +783,7 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
                                dlm_free_rsb(r);
                        }
                }
-               write_unlock(&ls->ls_rsbtbl[i].lock);
+               spin_unlock(&ls->ls_rsbtbl[i].lock);
        }
 }
 
index 965abb8bc7ff7297d565ad1d2c710acb05373baa..3c19027331faa0cc9d1ec9a6195096a112434a2a 100644 (file)
@@ -5,6 +5,7 @@
  * This file contains the system call numbers.
  */
 
+#define __NR_restart_syscall     0
 #define __NR_exit                1
 #define __NR_fork                2
 #define __NR_read                3
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
-/* whitelist for checksyscalls */
-#define __IGNORE_restart_syscall
-
 /*
  * "Conditional" syscalls
  *
index 1e65ebc2a3dbb5496d8ca6e82d091e25f9160ccd..b2dd31ca17101fede259112846789e48f9f42c9a 100644 (file)
@@ -241,7 +241,7 @@ struct dio_driver {
 
 extern int dio_find(int deviceid);
 extern unsigned long dio_scodetophysaddr(int scode);
-extern void dio_create_sysfs_dev_files(struct dio_dev *);
+extern int dio_create_sysfs_dev_files(struct dio_dev *);
 
 /* New-style probing */
 extern int dio_register_driver(struct dio_driver *);
index 4af1083e3287aa332491bc081d5b3ee2d30f6d13..93a4edb148b50815beb254a2a310373b50aff779 100644 (file)
        .private_value = (unsigned long)&xenum }
 #define SOC_DAPM_VALUE_ENUM(xname, xenum) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .info = snd_soc_info_value_enum_double, \
+       .info = snd_soc_info_enum_double, \
        .get = snd_soc_dapm_get_value_enum_double, \
        .put = snd_soc_dapm_put_value_enum_double, \
        .private_value = (unsigned long)&xenum }
index 9b930d34211666873670c93f732b38a11dec3437..24593ac3ea19528749da10d77aeb0ca1e00c3f94 100644 (file)
        .private_value = (unsigned long)&xenum }
 #define SOC_VALUE_ENUM(xname, xenum) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
-       .info = snd_soc_info_value_enum_double, \
+       .info = snd_soc_info_enum_double, \
        .get = snd_soc_get_value_enum_double, \
        .put = snd_soc_put_value_enum_double, \
        .private_value = (unsigned long)&xenum }
@@ -211,8 +211,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
-int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
@@ -414,17 +412,6 @@ struct soc_mixer_control {
 
 /* enumerated kcontrol */
 struct soc_enum {
-       unsigned short reg;
-       unsigned short reg2;
-       unsigned char shift_l;
-       unsigned char shift_r;
-       unsigned int max;
-       const char **texts;
-       void *dapm;
-};
-
-/* semi enumerated kcontrol */
-struct soc_value_enum {
        unsigned short reg;
        unsigned short reg2;
        unsigned char shift_l;
index 4d45bd63718b804afd012cba07e628f457525bdf..57d9f154c88b96ad5df87893f70e5690449c1d31 100644 (file)
@@ -851,8 +851,9 @@ static int __init AtaIrqInit(void)
        mfp.tim_dt_a = 1;       /* Cause interrupt after first event. */
        mfp.tim_ct_a = 8;       /* Turn on event counting. */
        /* Register interrupt handler. */
-       request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
-                   AtaInterrupt);
+       if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
+                       AtaInterrupt))
+               return 0;
        mfp.int_en_a |= 0x20;   /* Turn interrupt on. */
        mfp.int_mk_a |= 0x20;
        return 1;
index 1855b14d90c3922989abfd43a0e53b57423174f6..99bcb21c22819de40784e4ea5873104a9d16945e 100644 (file)
@@ -371,8 +371,9 @@ static void Q40Free(void *ptr, unsigned int size)
 static int __init Q40IrqInit(void)
 {
        /* Register interrupt handler. */
-       request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
-                   "DMA sound", Q40Interrupt);
+       if (request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
+                   "DMA sound", Q40Interrupt))
+               return 0;
 
        return(1);
 }
@@ -401,6 +402,7 @@ static void Q40PlayNextFrame(int index)
        u_char *start;
        u_long size;
        u_char speed;
+       int error;
 
        /* used by Q40Play() if all doubts whether there really is something
         * to be played are already wiped out.
@@ -419,11 +421,13 @@ static void Q40PlayNextFrame(int index)
        master_outb( 0,SAMPLE_ENABLE_REG);
        free_irq(Q40_IRQ_SAMPLE, Q40Interrupt);
        if (dmasound.soft.stereo)
-               request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
-                   "Q40 sound", Q40Interrupt);
+               error = request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
+                                   "Q40 sound", Q40Interrupt);
          else
-               request_irq(Q40_IRQ_SAMPLE, Q40MonoInterrupt, 0,
-                   "Q40 sound", Q40Interrupt);
+               error = request_irq(Q40_IRQ_SAMPLE, Q40MonoInterrupt, 0,
+                                   "Q40 sound", Q40Interrupt);
+       if (error && printk_ratelimit())
+               pr_err("Couldn't register sound interrupt\n");
 
        master_outb( speed, SAMPLE_RATE_REG);
        master_outb( 1,SAMPLE_CLEAR_REG);
index e00421c0d8ba5048d968ce412d7e3493a83688e2..960fd79703848e153cb44fcff27ed58f97ad3337 100644 (file)
@@ -135,7 +135,6 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
        struct hda_beep *beep = codec->beep;
        if (beep) {
                cancel_work_sync(&beep->beep_work);
-               flush_scheduled_work();
 
                input_unregister_device(beep->dev);
                kfree(beep);
index e16cf63821aeab8e46edf1921d5ae094f7f55ff9..3c596da2b9b5aa07e168797630e79a2d56050340 100644 (file)
@@ -373,7 +373,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
        unsol->queue[wp] = res;
        unsol->queue[wp + 1] = res_ex;
 
-       schedule_work(&unsol->work);
+       queue_work(bus->workq, &unsol->work);
 
        return 0;
 }
@@ -437,15 +437,17 @@ static int snd_hda_bus_free(struct hda_bus *bus)
 
        if (!bus)
                return 0;
-       if (bus->unsol) {
-               flush_scheduled_work();
+       if (bus->workq)
+               flush_workqueue(bus->workq);
+       if (bus->unsol)
                kfree(bus->unsol);
-       }
        list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
                snd_hda_codec_free(codec);
        }
        if (bus->ops.private_free)
                bus->ops.private_free(bus);
+       if (bus->workq)
+               destroy_workqueue(bus->workq);
        kfree(bus);
        return 0;
 }
@@ -485,6 +487,7 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
 {
        struct hda_bus *bus;
        int err;
+       char qname[8];
        static struct snd_device_ops dev_ops = {
                .dev_register = snd_hda_bus_dev_register,
                .dev_free = snd_hda_bus_dev_free,
@@ -514,6 +517,14 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
        mutex_init(&bus->cmd_mutex);
        INIT_LIST_HEAD(&bus->codec_list);
 
+       snprintf(qname, sizeof(qname), "hda%d", card->number);
+       bus->workq = create_workqueue(qname);
+       if (!bus->workq) {
+               snd_printk(KERN_ERR "cannot create workqueue %s\n", qname);
+               kfree(bus);
+               return -ENOMEM;
+       }
+
        err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
        if (err < 0) {
                snd_hda_bus_free(bus);
@@ -684,7 +695,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
                return;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        cancel_delayed_work(&codec->power_work);
-       flush_scheduled_work();
+       flush_workqueue(codec->bus->workq);
 #endif
        list_del(&codec->list);
        snd_array_free(&codec->mixers);
@@ -735,6 +746,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
        codec->bus = bus;
        codec->addr = codec_addr;
        mutex_init(&codec->spdif_mutex);
+       mutex_init(&codec->control_mutex);
        init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
        init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
        snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
@@ -1272,7 +1284,7 @@ void snd_hda_codec_reset(struct hda_codec *codec)
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        cancel_delayed_work(&codec->power_work);
-       flush_scheduled_work();
+       flush_workqueue(codec->bus->workq);
 #endif
        snd_hda_ctls_clear(codec);
        /* relase PCMs */
@@ -1418,12 +1430,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
        unsigned long pval;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        pval = kcontrol->private_value;
        kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
        err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
        kcontrol->private_value = pval;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
@@ -1435,7 +1447,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
        unsigned long pval;
        int i, indices, err = 0, change = 0;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        pval = kcontrol->private_value;
        indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
        for (i = 0; i < indices; i++) {
@@ -1447,7 +1459,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
                change |= err;
        }
        kcontrol->private_value = pval;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
@@ -1462,12 +1474,12 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
        struct hda_bind_ctls *c;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        c = (struct hda_bind_ctls *)kcontrol->private_value;
        kcontrol->private_value = *c->values;
        err = c->ops->info(kcontrol, uinfo);
        kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
@@ -1479,12 +1491,12 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
        struct hda_bind_ctls *c;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        c = (struct hda_bind_ctls *)kcontrol->private_value;
        kcontrol->private_value = *c->values;
        err = c->ops->get(kcontrol, ucontrol);
        kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
@@ -1497,7 +1509,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
        unsigned long *vals;
        int err = 0, change = 0;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        c = (struct hda_bind_ctls *)kcontrol->private_value;
        for (vals = c->values; *vals; vals++) {
                kcontrol->private_value = *vals;
@@ -1507,7 +1519,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
                change |= err;
        }
        kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
@@ -1519,12 +1531,12 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        struct hda_bind_ctls *c;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        c = (struct hda_bind_ctls *)kcontrol->private_value;
        kcontrol->private_value = *c->values;
        err = c->ops->tlv(kcontrol, op_flag, size, tlv);
        kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->spdif_mutex);
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
index 729fc7642d7f50f0d01f558ba584ca17b2c6137a..5810ef5884029bba949a4ba8b396478766c93d8f 100644 (file)
@@ -614,6 +614,7 @@ struct hda_bus {
 
        /* unsolicited event queue */
        struct hda_bus_unsolicited *unsol;
+       struct workqueue_struct *workq; /* common workqueue for codecs */
 
        /* assigned PCMs */
        DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
@@ -771,6 +772,7 @@ struct hda_codec {
        struct hda_cache_rec cmd_cache; /* cache for other commands */
 
        struct mutex spdif_mutex;
+       struct mutex control_mutex;
        unsigned int spdif_status;      /* IEC958 status bits */
        unsigned short spdif_ctls;      /* SPDIF control bits */
        unsigned int spdif_in_enable;   /* SPDIF input enable? */
index f04de115ee11eed00fa45304414444c1715ed1be..11e791b965f6a772588ac7dff64437b3ec836e70 100644 (file)
@@ -996,10 +996,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
                                spin_unlock(&chip->reg_lock);
                                snd_pcm_period_elapsed(azx_dev->substream);
                                spin_lock(&chip->reg_lock);
-                       } else {
+                       } else if (chip->bus && chip->bus->workq) {
                                /* bogus IRQ, process it later */
                                azx_dev->irq_pending = 1;
-                               schedule_work(&chip->irq_pending_work);
+                               queue_work(chip->bus->workq,
+                                          &chip->irq_pending_work);
                        }
                }
        }
@@ -1741,7 +1742,6 @@ static void azx_clear_irq_pending(struct azx *chip)
        for (i = 0; i < chip->num_streams; i++)
                chip->azx_dev[i].irq_pending = 0;
        spin_unlock_irq(&chip->reg_lock);
-       flush_scheduled_work();
 }
 
 static struct snd_pcm_ops azx_pcm_ops = {
index 26247cfe749dde5a1de3ce388ff34bbd33dff1ba..2e7371ec2e2319fcebe123ed36fe87b58e5e4cbf 100644 (file)
@@ -3900,6 +3900,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
 
 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
+       SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
        SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
@@ -4262,13 +4263,13 @@ static int patch_ad1882(struct hda_codec *codec)
        spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
        spec->adc_nids = ad1882_adc_nids;
        spec->capsrc_nids = ad1882_capsrc_nids;
-       if (codec->vendor_id == 0x11d1882)
+       if (codec->vendor_id == 0x11d41882)
                spec->input_mux = &ad1882_capture_source;
        else
                spec->input_mux = &ad1882a_capture_source;
        spec->num_mixers = 2;
        spec->mixers[0] = ad1882_base_mixers;
-       if (codec->vendor_id == 0x11d1882)
+       if (codec->vendor_id == 0x11d41882)
                spec->mixers[1] = ad1882_loopback_mixers;
        else
                spec->mixers[1] = ad1882a_loopback_mixers;
index 0270fda0bda5f722e2d8f9833b07bad216815fc7..96952a37d8847c4b2c667bdfb5d249235f07aa59 100644 (file)
@@ -162,12 +162,14 @@ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
        { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi },
        { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi },
        { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi },
+       { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi },
        {} /* terminator */
 };
 
 MODULE_ALIAS("snd-hda-codec-id:10de0002");
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
+MODULE_ALIAS("snd-hda-codec-id:10de8001");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
index 9065ebf9c065a52d761d27d74a72728513f2af5b..ea4c88fe05c40cb36ccd7e78bf2781702925c823 100644 (file)
@@ -1502,11 +1502,11 @@ static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
        struct alc_spec *spec = codec->spec;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
                                                      HDA_INPUT);
        err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
-       mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 
@@ -1517,11 +1517,11 @@ static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        struct alc_spec *spec = codec->spec;
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
                                                      HDA_INPUT);
        err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
-       mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 
@@ -1537,11 +1537,11 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
        int err;
 
-       mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_lock(&codec->control_mutex);
        kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
                                                      3, 0, HDA_INPUT);
        err = func(kcontrol, ucontrol);
-       mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+       mutex_unlock(&codec->control_mutex);
        return err;
 }
 
@@ -8461,6 +8461,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
                ALC888_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
+               ALC888_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
+               ALC888_ACER_ASPIRE_4930G),
        SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
        SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -8522,6 +8526,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
        SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
+       SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
        {}
 };
@@ -11689,6 +11694,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
                                                ALC268_ACER_ASPIRE_ONE),
        SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
+       SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron Mini9", ALC268_DELL),
        SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
        SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
index fd0f338374a7cfbea4fffacf624c3c148c63c6c9..ea370a4f86d5a2c74d97b176d977a55947ab120e 100644 (file)
@@ -197,7 +197,7 @@ static const char *twl4030_earpiece_texts[] =
 static const unsigned int twl4030_earpiece_values[] =
                {0x0, 0x1, 0x2, 0x4};
 
-static const struct soc_value_enum twl4030_earpiece_enum =
+static const struct soc_enum twl4030_earpiece_enum =
        SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
                        ARRAY_SIZE(twl4030_earpiece_texts),
                        twl4030_earpiece_texts,
@@ -213,7 +213,7 @@ static const char *twl4030_predrivel_texts[] =
 static const unsigned int twl4030_predrivel_values[] =
                {0x0, 0x1, 0x2, 0x4};
 
-static const struct soc_value_enum twl4030_predrivel_enum =
+static const struct soc_enum twl4030_predrivel_enum =
        SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
                        ARRAY_SIZE(twl4030_predrivel_texts),
                        twl4030_predrivel_texts,
@@ -229,7 +229,7 @@ static const char *twl4030_predriver_texts[] =
 static const unsigned int twl4030_predriver_values[] =
                {0x0, 0x1, 0x2, 0x4};
 
-static const struct soc_value_enum twl4030_predriver_enum =
+static const struct soc_enum twl4030_predriver_enum =
        SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
                        ARRAY_SIZE(twl4030_predriver_texts),
                        twl4030_predriver_texts,
@@ -317,7 +317,7 @@ static const char *twl4030_analoglmic_texts[] =
 static const unsigned int twl4030_analoglmic_values[] =
                {0x0, 0x1, 0x2, 0x4, 0x8};
 
-static const struct soc_value_enum twl4030_analoglmic_enum =
+static const struct soc_enum twl4030_analoglmic_enum =
        SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf,
                        ARRAY_SIZE(twl4030_analoglmic_texts),
                        twl4030_analoglmic_texts,
@@ -333,7 +333,7 @@ static const char *twl4030_analogrmic_texts[] =
 static const unsigned int twl4030_analogrmic_values[] =
                {0x0, 0x1, 0x4};
 
-static const struct soc_value_enum twl4030_analogrmic_enum =
+static const struct soc_enum twl4030_analogrmic_enum =
        SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5,
                        ARRAY_SIZE(twl4030_analogrmic_texts),
                        twl4030_analogrmic_texts,
@@ -1280,6 +1280,8 @@ static int twl4030_remove(struct platform_device *pdev)
        struct snd_soc_codec *codec = socdev->codec;
 
        printk(KERN_INFO "TWL4030 Audio Codec remove\n");
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
        kfree(codec);
 
        return 0;
index 6cbe7e82f2385f1a405372412b4b2ff1f6db7ef5..55fdb4abb1796dc728dfedd147dc09eaf01298fc 100644 (file)
@@ -1584,37 +1584,6 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
 
-/**
- * snd_soc_info_value_enum_double - semi enumerated double mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a double semi enumerated
- * mixer control.
- *
- * Semi enumerated mixer: the enumerated items are referred as values. Can be
- * used for handling bitfield coded enumeration for example.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo)
-{
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
-       uinfo->value.enumerated.items = e->max;
-
-       if (uinfo->value.enumerated.item > e->max - 1)
-               uinfo->value.enumerated.item = e->max - 1;
-       strcpy(uinfo->value.enumerated.name,
-               e->texts[uinfo->value.enumerated.item]);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_value_enum_double);
-
 /**
  * snd_soc_get_value_enum_double - semi enumerated double mixer get callback
  * @kcontrol: mixer control
@@ -1631,8 +1600,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        unsigned short reg_val, val, mux;
 
        reg_val = snd_soc_read(codec, e->reg);
@@ -1671,8 +1639,7 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        unsigned short val;
        unsigned short mask;
 
index ad0d801677c13ccd64eaa7942f1c120ecb07b144..493a4e8aa27357cb74d07ed9858b7cdbc8c2e7e2 100644 (file)
@@ -137,7 +137,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
        }
        break;
        case snd_soc_dapm_value_mux: {
-               struct soc_value_enum *e = (struct soc_value_enum *)
+               struct soc_enum *e = (struct soc_enum *)
                        w->kcontrols[i].private_value;
                int val, item;
 
@@ -200,30 +200,6 @@ static int dapm_connect_mux(struct snd_soc_codec *codec,
        return -ENODEV;
 }
 
-/* connect value_mux widget to it's interconnecting audio paths */
-static int dapm_connect_value_mux(struct snd_soc_codec *codec,
-       struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
-       struct snd_soc_dapm_path *path, const char *control_name,
-       const struct snd_kcontrol_new *kcontrol)
-{
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
-       int i;
-
-       for (i = 0; i < e->max; i++) {
-               if (!(strcmp(control_name, e->texts[i]))) {
-                       list_add(&path->list, &codec->dapm_paths);
-                       list_add(&path->list_sink, &dest->sources);
-                       list_add(&path->list_source, &src->sinks);
-                       path->name = (char *)e->texts[i];
-                       dapm_set_path_status(dest, path, 0);
-                       return 0;
-               }
-       }
-
-       return -ENODEV;
-}
-
 /* connect mixer widget to it's interconnecting audio paths */
 static int dapm_connect_mixer(struct snd_soc_codec *codec,
        struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
@@ -774,45 +750,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
        return 0;
 }
 
-/* test and update the power status of a value_mux widget */
-static int dapm_value_mux_update_power(struct snd_soc_dapm_widget *widget,
-                                struct snd_kcontrol *kcontrol, int mask,
-                                int mux, int val, struct soc_value_enum *e)
-{
-       struct snd_soc_dapm_path *path;
-       int found = 0;
-
-       if (widget->id != snd_soc_dapm_value_mux)
-               return -ENODEV;
-
-       if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
-               return 0;
-
-       /* find dapm widget path assoc with kcontrol */
-       list_for_each_entry(path, &widget->codec->dapm_paths, list) {
-               if (path->kcontrol != kcontrol)
-                       continue;
-
-               if (!path->name || !e->texts[mux])
-                       continue;
-
-               found = 1;
-               /* we now need to match the string in the enum to the path */
-               if (!(strcmp(path->name, e->texts[mux])))
-                       path->connect = 1; /* new connection */
-               else
-                       path->connect = 0; /* old connection must be
-                                             powered down */
-       }
-
-       if (found) {
-               dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
-               dump_dapm(widget->codec, "mux power update");
-       }
-
-       return 0;
-}
-
 /* test and update the power status of a mixer or switch widget */
 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
                                   struct snd_kcontrol *kcontrol, int reg,
@@ -1045,17 +982,12 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
                path->connect = 1;
                return 0;
        case snd_soc_dapm_mux:
+       case snd_soc_dapm_value_mux:
                ret = dapm_connect_mux(codec, wsource, wsink, path, control,
                        &wsink->kcontrols[0]);
                if (ret != 0)
                        goto err;
                break;
-       case snd_soc_dapm_value_mux:
-               ret = dapm_connect_value_mux(codec, wsource, wsink, path,
-                       control, &wsink->kcontrols[0]);
-               if (ret != 0)
-                       goto err;
-               break;
        case snd_soc_dapm_switch:
        case snd_soc_dapm_mixer:
                ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
@@ -1382,8 +1314,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        unsigned short reg_val, val, mux;
 
        reg_val = snd_soc_read(widget->codec, e->reg);
@@ -1423,8 +1354,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
-       struct soc_value_enum *e = (struct soc_value_enum *)
-                       kcontrol->private_value;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        unsigned short val, mux;
        unsigned short mask;
        int ret = 0;
@@ -1443,7 +1373,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 
        mutex_lock(&widget->codec->mutex);
        widget->value = val;
-       dapm_value_mux_update_power(widget, kcontrol, mask, mux, val, e);
+       dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
        if (widget->event) {
                if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
                        ret = widget->event(widget,
index a62500e387a654b904a2cdfda9c6b16f319bfa1b..41c36b055f6b3f980b7c8217ce6b1496efe6bc43 100644 (file)
@@ -42,7 +42,7 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.10");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
index f9fbdbae269d21491d2dc84f726cfc12cdf51261..ab56e738c5fc021f71af01365c5f164f64779cb2 100644 (file)
@@ -75,6 +75,7 @@ struct snd_usb_caiaqdev {
        wait_queue_head_t ep1_wait_queue;
        wait_queue_head_t prepare_wait_queue;
        int spec_received, audio_parm_answer;
+       int midi_out_active;
 
        char vendor_name[CAIAQ_USB_STR_LEN];
        char product_name[CAIAQ_USB_STR_LEN];
index 30b57f97c6e411221517f9a8c3d0a5e1a42036b0..f19fd360c9367b76fdb4df440743fea019dc7d77 100644 (file)
@@ -59,6 +59,11 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea
 
 static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
 {
+       struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
+       if (dev->midi_out_active) {
+               usb_kill_urb(&dev->midi_out_urb);
+               dev->midi_out_active = 0;
+       }
        return 0;
 }
 
@@ -69,7 +74,8 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
        
        dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
        dev->midi_out_buf[1] = 0; /* port */
-       len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3);
+       len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3,
+                                  EP1_BUFSIZE - 3);
        
        if (len <= 0)
                return;
@@ -79,24 +85,24 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
        
        ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC);
        if (ret < 0)
-               log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n",
-                               substream, ret);
+               log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
+                   "ret=%d, len=%d\n",
+                   substream, ret, len);
+       else
+               dev->midi_out_active = 1;
 }
 
 static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
 {
        struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
        
-       if (dev->midi_out_substream != NULL)
-               return;
-       
-       if (!up) {
+       if (up) {
+               dev->midi_out_substream = substream;
+               if (!dev->midi_out_active)
+                       snd_usb_caiaq_midi_send(dev, substream);
+       } else {
                dev->midi_out_substream = NULL;
-               return;
        }
-       
-       dev->midi_out_substream = substream;
-       snd_usb_caiaq_midi_send(dev, substream);
 }
 
 
@@ -161,16 +167,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
 void snd_usb_caiaq_midi_output_done(struct urb* urb)
 {
        struct snd_usb_caiaqdev *dev = urb->context;
-       char *buf = urb->transfer_buffer;
        
+       dev->midi_out_active = 0;
        if (urb->status != 0)
                return;
 
        if (!dev->midi_out_substream)
                return;
 
-       snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]);
-       dev->midi_out_substream = NULL;
        snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);
 }