diff options
Diffstat (limited to 'drivers/char')
39 files changed, 653 insertions, 755 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index ef683ebd367c..ec9dc3d53f18 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -374,20 +374,6 @@ config ISTALLION To compile this driver as a module, choose M here: the module will be called istallion. -config AU1000_UART - bool "Enable Au1000 UART Support" - depends on SERIAL_NONSTANDARD && MIPS - help - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use serial ports, say Y. Otherwise, say N. - -config AU1000_SERIAL_CONSOLE - bool "Enable Au1000 serial console" - depends on AU1000_UART - help - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use a console on a serial port, say Y. Otherwise, say N. - config SERIAL_DEC bool "DECstation serial support" depends on MACH_DECSTATION @@ -815,7 +801,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 && !SUPERH + depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -993,15 +979,14 @@ config GPIO_VR41XX depends on CPU_VR41XX config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" + tristate "RAW driver (/dev/raw/rawN)" depends on BLOCK help - The raw driver permits block devices to be bound to /dev/raw/rawN. - Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. + The raw driver permits block devices to be bound to /dev/raw/rawN. + Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. See the raw(8) manpage for more details. - The raw driver is deprecated and will be removed soon. - Applications should simply open the device (eg /dev/hda1) + Applications should preferably open the device (eg /dev/hda1) with the O_DIRECT flag. config MAX_RAW_DEVS diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 2f56ecc035aa..f2996a95eb07 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -15,6 +15,7 @@ obj-y += misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o +obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_ESPSERIAL) += esp.o obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index e6c534e62846..df0ddf14b85c 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -462,9 +462,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing. * With this lot disabled, we should prevent lockups. */ if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) { - u8 revision=0; - pci_read_config_byte(pdev, PCI_REVISION_ID, &revision); - if (revision == 0x10 || revision == 0x11) { + if (pdev->revision == 0x10 || pdev->revision == 0x11) { agp_bridge->flags = AGP_ERRATA_FASTWRITES; agp_bridge->flags |= AGP_ERRATA_SBA; agp_bridge->flags |= AGP_ERRATA_1X; diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 801abdd29066..d95662e96326 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -367,10 +367,8 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) { char *revstring; - u8 rev_id; - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); - switch (rev_id) { + switch (pdev->revision) { case 0x01: revstring="A0"; break; case 0x02: revstring="A1"; break; case 0x11: revstring="B0"; break; @@ -386,7 +384,7 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data * Work around errata. * Chips before B2 stepping incorrectly reporting v3.5 */ - if (rev_id < 0x13) { + if (pdev->revision < 0x13) { printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); bridge->major_version = 3; bridge->minor_version = 0; diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index ebdd6dd66edb..1b47c89a1b99 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -321,7 +321,7 @@ EXPORT_SYMBOL(agp_try_unsupported_boot); static int __init agp_init(void) { if (!agp_off) - printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n", + printk(KERN_INFO "Linux agpgart interface v%d.%d\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); return 0; } diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4eaceabd8cea..7b02bf1289a2 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -738,6 +738,7 @@ static void change_speed(struct async_struct *info, } /* If the quotient is zero refuse the change */ if (!quot && old_termios) { + /* FIXME: Will need updating for new tty in the end */ info->tty->termios->c_cflag &= ~CBAUD; info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); baud = tty_get_baud_rate(info->tty); @@ -783,7 +784,6 @@ static void change_speed(struct async_struct *info, /* * Set up parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) info->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (I_INPCK(info->tty)) @@ -1367,11 +1367,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) unsigned long flags; unsigned int cflag = tty->termios->c_cflag; - if ( (cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - change_speed(info, old_termios); /* Handle transition to B0 status */ diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index fd40b959afdd..4b3916f54909 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -177,6 +177,7 @@ struct uni_pagedir { unsigned long refcount; unsigned long sum; unsigned char *inverse_translations[4]; + u16 *inverse_trans_unicode; int readonly; }; @@ -207,6 +208,41 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int } } +static void set_inverse_trans_unicode(struct vc_data *conp, + struct uni_pagedir *p) +{ + int i, j, k, glyph; + u16 **p1, *p2; + u16 *q; + + if (!p) return; + q = p->inverse_trans_unicode; + if (!q) { + q = p->inverse_trans_unicode = + kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL); + if (!q) + return; + } + memset(q, 0, MAX_GLYPH * sizeof(u16)); + + for (i = 0; i < 32; i++) { + p1 = p->uni_pgdir[i]; + if (!p1) + continue; + for (j = 0; j < 32; j++) { + p2 = p1[j]; + if (!p2) + continue; + for (k = 0; k < 64; k++) { + glyph = p2[k]; + if (glyph >= 0 && glyph < MAX_GLYPH + && q[glyph] < 32) + q[glyph] = (i << 11) + (j << 6) + k; + } + } + } +} + unsigned short *set_translate(int m, struct vc_data *vc) { inv_translate[vc->vc_num] = m; @@ -217,19 +253,29 @@ unsigned short *set_translate(int m, struct vc_data *vc) * Inverse translation is impossible for several reasons: * 1. The font<->character maps are not 1-1. * 2. The text may have been written while a different translation map - * was active, or using Unicode. + * was active. * Still, it is now possible to a certain extent to cut and paste non-ASCII. */ -unsigned char inverse_translate(struct vc_data *conp, int glyph) +u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode) { struct uni_pagedir *p; + int m; if (glyph < 0 || glyph >= MAX_GLYPH) return 0; - else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) || - !p->inverse_translations[inv_translate[conp->vc_num]]) + else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc)) return glyph; - else - return p->inverse_translations[inv_translate[conp->vc_num]][glyph]; + else if (use_unicode) { + if (!p->inverse_trans_unicode) + return glyph; + else + return p->inverse_trans_unicode[glyph]; + } else { + m = inv_translate[conp->vc_num]; + if (!p->inverse_translations[m]) + return glyph; + else + return p->inverse_translations[m][glyph]; + } } static void update_user_maps(void) @@ -243,6 +289,7 @@ static void update_user_maps(void) p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc; if (p && p != q) { set_inverse_transl(vc_cons[i].d, p, USER_MAP); + set_inverse_trans_unicode(vc_cons[i].d, p); q = p; } } @@ -353,6 +400,10 @@ static void con_release_unimap(struct uni_pagedir *p) kfree(p->inverse_translations[i]); p->inverse_translations[i] = NULL; } + if (p->inverse_trans_unicode) { + kfree(p->inverse_trans_unicode); + p->inverse_trans_unicode = NULL; + } } void con_free_unimap(struct vc_data *vc) @@ -511,6 +562,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) for (i = 0; i <= 3; i++) set_inverse_transl(vc, p, i); /* Update all inverse translations */ + set_inverse_trans_unicode(vc, p); return err; } @@ -561,6 +613,7 @@ int con_set_default_unimap(struct vc_data *vc) for (i = 0; i <= 3; i++) set_inverse_transl(vc, p, i); /* Update all inverse translations */ + set_inverse_trans_unicode(vc, p); dflt = p; return err; } @@ -617,6 +670,19 @@ void con_protect_unimap(struct vc_data *vc, int rdonly) p->readonly = rdonly; } +/* may be called during an interrupt */ +u32 conv_8bit_to_uni(unsigned char c) +{ + /* + * Always use USER_MAP. This function is used by the keyboard, + * which shouldn't be affected by G0/G1 switching, etc. + * If the user map still contains default values, i.e. the + * direct-to-font mapping, then assume user is using Latin1. + */ + unsigned short uni = translations[USER_MAP][c]; + return uni == (0xf000 | c) ? c : uni; +} + int conv_uni_to_pc(struct vc_data *conp, long ucs) { diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index ca376b92162c..e04005b5f8a6 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -4127,10 +4127,6 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); #endif - if (tty->termios->c_cflag == old_termios->c_cflag && - (tty->termios->c_iflag & (IXON | IXANY)) == - (old_termios->c_iflag & (IXON | IXANY))) - return; set_line_char(info); if ((old_termios->c_cflag & CRTSCTS) && diff --git a/drivers/char/esp.c b/drivers/char/esp.c index d1bfbaa2aa02..74cd5118af57 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1121,8 +1121,6 @@ static void change_speed(struct esp_struct *info) /* * Set up parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (I_INPCK(info->tty)) info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; @@ -1920,11 +1918,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) struct esp_struct *info = (struct esp_struct *)tty->driver_data; unsigned long flags; - if ( (tty->termios->c_cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - change_speed(info); spin_lock_irqsave(&info->lock, flags); diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 8ea02755b1c9..8facf3e25c49 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -43,16 +43,6 @@ static int gs_debug; #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) #define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) -#define NEW_WRITE_LOCKING 1 -#if NEW_WRITE_LOCKING -#define DECL /* Nothing */ -#define LOCKIT mutex_lock(& port->port_write_mutex); -#define RELEASEIT mutex_unlock(&port->port_write_mutex); -#else -#define DECL unsigned long flags; -#define LOCKIT save_flags (flags);cli () -#define RELEASEIT restore_flags (flags) -#endif #define RS_EVENT_WRITE_WAKEUP 1 @@ -62,7 +52,6 @@ module_param(gs_debug, int, 0644); void gs_put_char(struct tty_struct * tty, unsigned char ch) { struct gs_port *port; - DECL func_enter (); @@ -75,11 +64,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) if (! (port->flags & ASYNC_INITIALIZED)) return; /* Take a lock on the serial tranmit buffer! */ - LOCKIT; + mutex_lock(& port->port_write_mutex); if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ - RELEASEIT; + mutex_unlock(&port->port_write_mutex); return; } @@ -87,13 +76,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) port->xmit_head &= SERIAL_XMIT_SIZE - 1; port->xmit_cnt++; /* Characters in buffer */ - RELEASEIT; + mutex_unlock(&port->port_write_mutex); func_exit (); } -#ifdef NEW_WRITE_LOCKING - /* > Problems to take into account are: > -1- Interrupts that empty part of the buffer. @@ -166,90 +153,6 @@ int gs_write(struct tty_struct * tty, func_exit (); return total; } -#else -/* -> Problems to take into account are: -> -1- Interrupts that empty part of the buffer. -> -2- page faults on the access to userspace. -> -3- Other processes that are also trying to do a "write". -*/ - -int gs_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - struct gs_port *port; - int c, total = 0; - int t; - unsigned long flags; - - func_enter (); - - /* The standard serial driver returns 0 in this case. - That sounds to me as "No error, I just didn't get to writing any - bytes. Feel free to try again." - The "official" way to write n bytes from buf is: - - for (nwritten = 0;nwritten < n;nwritten += rv) { - rv = write (fd, buf+nwritten, n-nwritten); - if (rv < 0) break; // Error: bail out. // - } - - which will loop endlessly in this case. The manual page for write - agrees with me. In practise almost everybody writes - "write (fd, buf,n);" but some people might have had to deal with - incomplete writes in the past and correctly implemented it by now... - */ - - if (!tty) return -EIO; - - port = tty->driver_data; - if (!port || !port->xmit_buf) - return -EIO; - - local_save_flags(flags); - while (1) { - cli(); - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_mutex. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) { - local_restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; - local_restore_flags(flags); - buf += c; - count -= c; - total += c; - } - - if (port->xmit_cnt && - !tty->stopped && - !tty->hw_stopped && - !(port->flags & GS_TX_INTEN)) { - port->flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); - return total; -} - -#endif @@ -737,23 +640,6 @@ void gs_set_termios (struct tty_struct * tty, gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); } - /* This is an optimization that is only allowed for dumb cards */ - /* Smart cards require knowledge of iflags and oflags too: that - might change hardware cooking mode.... */ - if (old_termios) { - if( (tiosp->c_iflag == old_termios->c_iflag) - && (tiosp->c_oflag == old_termios->c_oflag) - && (tiosp->c_cflag == old_termios->c_cflag) - && (tiosp->c_lflag == old_termios->c_lflag) - && (tiosp->c_line == old_termios->c_line) - && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { - gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); - return /* 0 */; - } - } else - gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " - "no optimization\n"); - if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 9e1fc02967ff..69f0a2993af0 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -173,7 +173,6 @@ static void gen_rtc_interrupt(unsigned long arg) static ssize_t gen_rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); unsigned long data; ssize_t retval; @@ -183,18 +182,10 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data) return -EAGAIN; - add_wait_queue(&gen_rtc_wait, &wait); - retval = -ERESTARTSYS; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - data = xchg(&gen_rtc_irq_data, 0); - if (data) - break; - if (signal_pending(current)) - goto out; - schedule(); - } + retval = wait_event_interruptible(gen_rtc_wait, + (data = xchg(&gen_rtc_irq_data, 0))); + if (retval) + goto out; /* first test allows optimizer to nuke this case for 32-bit machines */ if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { @@ -206,10 +197,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(unsigned long); } - out: - __set_current_state(TASK_RUNNING); - remove_wait_queue(&gen_rtc_wait, &wait); - +out: return retval; } diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 4ae9811d1a6c..753f46052b87 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -296,12 +296,10 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) == BIOS_CNTL_LOCK_ENABLE_MASK) { static __initdata /*const*/ char warning[] = - KERN_WARNING PFX "Firmware space is locked read-only. " - KERN_WARNING PFX "If you can't or\n don't want to " - KERN_WARNING PFX "disable this in firmware setup, and " - KERN_WARNING PFX "if\n you are certain that your " - KERN_WARNING PFX "system has a functional\n RNG, try" - KERN_WARNING PFX "using the 'no_fwh_detect' option.\n"; + KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" + KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" + KERN_WARNING PFX "you are certain that your system has a functional\n" + KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; if (no_fwh_detect) return -ENODEV; diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c index dd761a1e4f08..61ef013b8445 100644 --- a/drivers/char/ip2/i2ellis.c +++ b/drivers/char/ip2/i2ellis.c @@ -43,8 +43,6 @@ static void iiEnableMailIrqIIEX(i2eBordStrPtr); static void iiWriteMaskII(i2eBordStrPtr, unsigned char); static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); -static void ii2DelayTimer(unsigned int); -static void ii2DelayWakeup(unsigned long id); static void ii2Nop(void); //*************** @@ -55,8 +53,6 @@ static int ii2Safe; // Safe I/O address for delay routine static int iiDelayed; // Set when the iiResetDelay function is // called. Cleared when ANY board is reset. -static struct timer_list * pDelayTimer; // Used by iiDelayTimer -static wait_queue_head_t pDelayWait; // Used by iiDelayTimer static rwlock_t Dl_spinlock; //******** @@ -86,9 +82,6 @@ static rwlock_t Dl_spinlock; static void iiEllisInit(void) { - pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL ); - init_timer(pDelayTimer); - init_waitqueue_head(&pDelayWait); LOCK_INIT(&Dl_spinlock); } @@ -106,7 +99,6 @@ iiEllisInit(void) static void iiEllisCleanup(void) { - kfree(pDelayTimer); } //****************************************************************************** @@ -560,19 +552,6 @@ iiInitialize(i2eBordStrPtr pB) COMPLETE(pB, I2EE_GOOD); } -//======================================================= -// Delay Routines -// -// iiDelayIO -// iiNop -//======================================================= - -static void -ii2DelayWakeup(unsigned long id) -{ - wake_up_interruptible ( &pDelayWait ); -} - //****************************************************************************** // Function: ii2DelayTimer(mseconds) // Parameters: mseconds - number of milliseconds to delay @@ -594,28 +573,7 @@ ii2DelayWakeup(unsigned long id) static void ii2DelayTimer(unsigned int mseconds) { - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - - init_timer ( pDelayTimer ); - - add_wait_queue(&pDelayWait, &wait); - - set_current_state( TASK_INTERRUPTIBLE ); - - pDelayTimer->expires = jiffies + ( mseconds + 9 ) / 10; - pDelayTimer->function = ii2DelayWakeup; - pDelayTimer->data = 0; - - add_timer ( pDelayTimer ); - - schedule(); - - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pDelayWait, &wait); - - del_timer ( pDelayTimer ); + msleep_interruptible(mseconds); } #if 0 diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index b894f67fdf14..0baa8fab4ea7 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -2,11 +2,9 @@ # IPMI device configuration # -menu "IPMI" - depends on HAS_IOMEM - -config IPMI_HANDLER +menuconfig IPMI_HANDLER tristate 'IPMI top-level message handler' + depends on HAS_IOMEM help This enables the central IPMI message handler, required for IPMI to work. @@ -18,9 +16,10 @@ config IPMI_HANDLER If unsure, say N. +if IPMI_HANDLER + config IPMI_PANIC_EVENT bool 'Generate a panic event to all BMCs on a panic' - depends on IPMI_HANDLER help When a panic occurs, this will cause the IPMI message handler to generate an IPMI event describing the panic to each interface @@ -40,14 +39,12 @@ config IPMI_PANIC_STRING config IPMI_DEVICE_INTERFACE tristate 'Device interface for IPMI' - depends on IPMI_HANDLER help This provides an IOCTL interface to the IPMI message handler so userland processes may use IPMI. It supports poll() and select(). config IPMI_SI tristate 'IPMI System Interface handler' - depends on IPMI_HANDLER help Provides a driver for System Interfaces (KCS, SMIC, BT). Currently, only KCS and SMIC are supported. If @@ -55,15 +52,13 @@ config IPMI_SI config IPMI_WATCHDOG tristate 'IPMI Watchdog Timer' - depends on IPMI_HANDLER help This enables the IPMI watchdog timer. config IPMI_POWEROFF tristate 'IPMI Poweroff' - depends on IPMI_HANDLER help This enables a function to power off the system with IPMI if the IPMI management controller is capable of this. -endmenu +endif # IPMI_HANDLER diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8e222f2b80cc..b5df7e61aeb2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc) int err; bmc->device_id_attr.attr.name = "device_id"; - bmc->device_id_attr.attr.owner = THIS_MODULE; bmc->device_id_attr.attr.mode = S_IRUGO; bmc->device_id_attr.show = device_id_show; bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; - bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; bmc->revision_attr.attr.name = "revision"; - bmc->revision_attr.attr.owner = THIS_MODULE; bmc->revision_attr.attr.mode = S_IRUGO; bmc->revision_attr.show = revision_show; bmc->firmware_rev_attr.attr.name = "firmware_revision"; - bmc->firmware_rev_attr.attr.owner = THIS_MODULE; bmc->firmware_rev_attr.attr.mode = S_IRUGO; bmc->firmware_rev_attr.show = firmware_rev_show; bmc->version_attr.attr.name = "ipmi_version"; - bmc->version_attr.attr.owner = THIS_MODULE; bmc->version_attr.attr.mode = S_IRUGO; bmc->version_attr.show = ipmi_version_show; bmc->add_dev_support_attr.attr.name = "additional_device_support"; - bmc->add_dev_support_attr.attr.owner = THIS_MODULE; bmc->add_dev_support_attr.attr.mode = S_IRUGO; bmc->add_dev_support_attr.show = add_dev_support_show; bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; - bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; bmc->manufacturer_id_attr.attr.mode = S_IRUGO; bmc->manufacturer_id_attr.show = manufacturer_id_show; bmc->product_id_attr.attr.name = "product_id"; - bmc->product_id_attr.attr.owner = THIS_MODULE; bmc->product_id_attr.attr.mode = S_IRUGO; bmc->product_id_attr.show = product_id_show; bmc->guid_attr.attr.name = "guid"; - bmc->guid_attr.attr.owner = THIS_MODULE; bmc->guid_attr.attr.mode = S_IRUGO; bmc->guid_attr.show = guid_show; bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; - bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index e02893b7b300..b86186de7f07 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -679,7 +679,7 @@ static int ipmi_poweroff_init (void) { int rv; - printk ("Copyright (C) 2004 MontaVista Software -" + printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -" " IPMI Powerdown via sys_reboot.\n"); if (poweroff_powercycle) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 78e1b962fe35..4edfdda0cf99 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2857,7 +2857,7 @@ static int try_smi_init(struct smi_info *new_smi) mutex_unlock(&smi_infos_lock); - printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); + printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); return 0; diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7b279d1de4a2..809409922996 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -1753,9 +1753,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old) return; tiosp = tty->termios; - if ((tiosp->c_cflag == old->c_cflag) && - (tiosp->c_iflag == old->c_iflag)) - return; stli_mkasyport(portp, &aport, tiosp); stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 90965b4def5c..2ce0af1bd588 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -24,6 +24,7 @@ * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) */ +#include <linux/consolemap.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/tty.h> @@ -308,10 +309,9 @@ static void applkey(struct vc_data *vc, int key, char mode) * Many other routines do put_queue, but I think either * they produce ASCII, or they produce some user-assigned * string, and in both cases we might assume that it is - * in utf-8 already. UTF-8 is defined for words of up to 31 bits, - * but we need only 16 bits here + * in utf-8 already. */ -static void to_utf8(struct vc_data *vc, ushort c) +static void to_utf8(struct vc_data *vc, uint c) { if (c < 0x80) /* 0******* */ @@ -320,11 +320,21 @@ static void to_utf8(struct vc_data *vc, ushort c) /* 110***** 10****** */ put_queue(vc, 0xc0 | (c >> 6)); put_queue(vc, 0x80 | (c & 0x3f)); - } else { + } else if (c < 0x10000) { + if (c >= 0xD800 && c < 0xE000) + return; + if (c == 0xFFFF) + return; /* 1110**** 10****** 10****** */ put_queue(vc, 0xe0 | (c >> 12)); put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); put_queue(vc, 0x80 | (c & 0x3f)); + } else if (c < 0x110000) { + /* 11110*** 10****** 10****** 10****** */ + put_queue(vc, 0xf0 | (c >> 18)); + put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); + put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); + put_queue(vc, 0x80 | (c & 0x3f)); } } @@ -393,7 +403,7 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch) return d; if (kbd->kbdmode == VC_UNICODE) - to_utf8(vc, d); + to_utf8(vc, conv_8bit_to_uni(d)); else if (d < 0x100) put_queue(vc, d); @@ -407,7 +417,7 @@ static void fn_enter(struct vc_data *vc) { if (diacr) { if (kbd->kbdmode == VC_UNICODE) - to_utf8(vc, diacr); + to_utf8(vc, conv_8bit_to_uni(diacr)); else if (diacr < 0x100) put_queue(vc, diacr); diacr = 0; @@ -617,7 +627,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) return; } if (kbd->kbdmode == VC_UNICODE) - to_utf8(vc, value); + to_utf8(vc, conv_8bit_to_uni(value)); else if (value < 0x100) put_queue(vc, value); } @@ -775,7 +785,7 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag) /* kludge */ if (up_flag && shift_state != old_state && npadch != -1) { if (kbd->kbdmode == VC_UNICODE) - to_utf8(vc, npadch & 0xffff); + to_utf8(vc, npadch); else put_queue(vc, npadch & 0xff); npadch = -1; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 4e6fb9651a16..71c8cd7fa15f 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -67,25 +67,13 @@ extern int pmu_device_init(void); #ifdef CONFIG_PROC_FS static void *misc_seq_start(struct seq_file *seq, loff_t *pos) { - struct miscdevice *p; - loff_t off = 0; - mutex_lock(&misc_mtx); - list_for_each_entry(p, &misc_list, list) { - if (*pos == off++) - return p; - } - return NULL; + return seq_list_start(&misc_list, *pos); } static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct list_head *n = ((struct miscdevice *)v)->list.next; - - ++*pos; - - return (n != &misc_list) ? list_entry(n, struct miscdevice, list) - : NULL; + return seq_list_next(v, &misc_list, pos); } static void misc_seq_stop(struct seq_file *seq, void *v) @@ -95,7 +83,7 @@ static void misc_seq_stop(struct seq_file *seq, void *v) static int misc_seq_show(struct seq_file *seq, void *v) { - const struct miscdevice *p = v; + const struct miscdevice *p = list_entry(v, struct miscdevice, list); seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : ""); return 0; diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 7ac30612068b..c716ef0dd370 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -265,7 +265,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type) vdata->refcnt = ATOMIC_INIT(1); vma->vm_private_data = vdata; - vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP); + vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP); if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_ops = &mspec_vm_ops; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5953a45d7e96..2aee3fef0416 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -90,8 +90,6 @@ #define UART_MCR_AFE 0x20 #define UART_LSR_SPECIAL 0x1E -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ - IXON|IXOFF)) #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) @@ -1729,16 +1727,12 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi struct mxser_struct *info = tty->driver_data; unsigned long flags; - if ((tty->termios->c_cflag != old_termios->c_cflag) || - (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { + mxser_change_speed(info, old_termios); - mxser_change_speed(info, old_termios); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - mxser_start(tty); - } + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mxser_start(tty); } /* Handle sw stopped */ diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 6cde448cd5b2..6a563932ba19 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c @@ -72,8 +72,6 @@ #define UART_MCR_AFE 0x20 #define UART_LSR_SPECIAL 0x1E -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ - IXON|IXOFF)) #define C168_ASIC_ID 1 #define C104_ASIC_ID 2 @@ -1560,7 +1558,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) return -EFAULT; return 0; case MOXA_ASPP_MON_EXT: { - int status, p, shiftbit; + int p, shiftbit; unsigned long opmode; unsigned cflag, iflag; @@ -1990,18 +1988,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi struct mxser_port *info = tty->driver_data; unsigned long flags; - if ((tty->termios->c_cflag != old_termios->c_cflag) || - (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { - - spin_lock_irqsave(&info->slock, flags); - mxser_change_speed(info, old_termios); - spin_unlock_irqrestore(&info->slock, flags); + spin_lock_irqsave(&info->slock, flags); + mxser_change_speed(info, old_termios); + spin_unlock_irqrestore(&info->slock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - mxser_start(tty); - } + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mxser_start(tty); } /* Handle sw stopped */ diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 337a87f86a3b..e8332f305d72 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -400,7 +400,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) /* Send the next block of data to device */ tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = tty->driver->write(tty, tbuf->buf, tbuf->count); - + + /* rollback was possible and has been done */ + if (actual == -ERESTARTSYS) { + n_hdlc->tbuf = tbuf; + break; + } /* if transmit error, throw frame away by */ /* pretending it was accepted by driver */ if (actual < 0) @@ -780,13 +785,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, poll_wait(filp, &tty->write_wait, wait); /* set bits for operations that won't block */ - if(n_hdlc->rx_buf_list.head) + if (n_hdlc->rx_buf_list.head) mask |= POLLIN | POLLRDNORM; /* readable */ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= POLLHUP; - if(tty_hung_up_p(filp)) + if (tty_hung_up_p(filp)) mask |= POLLHUP; - if(n_hdlc->tx_free_buf_list.head) + if (!tty_is_writelocked(tty) && + n_hdlc->tx_free_buf_list.head) mask |= POLLOUT | POLLWRNORM; /* writable */ } return mask; @@ -861,7 +867,7 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, spin_lock_irqsave(&list->spinlock,flags); buf->link=NULL; - if(list->tail) + if (list->tail) list->tail->link = buf; else list->head = buf; diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 14557a4822c0..6b918b80f73e 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1071,8 +1071,6 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, struct r3964_client_info *pClient; struct r3964_message *pMsg; struct r3964_client_message theMsg; - DECLARE_WAITQUEUE(wait, current); - int count; TRACE_L("read()"); @@ -1086,16 +1084,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, return -EAGAIN; } /* block until there is a message: */ - add_wait_queue(&pInfo->read_wait, &wait); -repeat: - __set_current_state(TASK_INTERRUPTIBLE); - pMsg = remove_msg(pInfo, pClient); - if (!pMsg && !signal_pending(current)) { - schedule(); - goto repeat; - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&pInfo->read_wait, &wait); + wait_event_interruptible(pInfo->read_wait, + (pMsg = remove_msg(pInfo, pClient))); } /* If we still haven't got a message, we must have been signalled */ diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 154f42203b05..038056911934 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -45,6 +45,8 @@ #include <linux/slab.h> #include <linux/poll.h> #include <linux/bitops.h> +#include <linux/audit.h> +#include <linux/file.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -78,6 +80,13 @@ static inline void free_buf(unsigned char *buf) free_page((unsigned long) buf); } +static inline int tty_put_user(struct tty_struct *tty, unsigned char x, + unsigned char __user *ptr) +{ + tty_audit_add_data(tty, &x, 1); + return put_user(x, ptr); +} + /** * n_tty_set__room - receive space * @tty: terminal @@ -1153,6 +1162,7 @@ static int copy_from_read_buf(struct tty_struct *tty, if (n) { retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); n -= retval; + tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n); spin_lock_irqsave(&tty->read_lock, flags); tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); tty->read_cnt -= n; @@ -1279,7 +1289,7 @@ do_it_again: break; cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; - if (put_user(cs, b++)) { + if (tty_put_user(tty, cs, b++)) { retval = -EFAULT; b--; break; @@ -1321,7 +1331,7 @@ do_it_again: /* Deal with packet mode. */ if (tty->packet && b == buf) { - if (put_user(TIOCPKT_DATA, b++)) { + if (tty_put_user(tty, TIOCPKT_DATA, b++)) { retval = -EFAULT; b--; break; @@ -1352,15 +1362,17 @@ do_it_again: spin_unlock_irqrestore(&tty->read_lock, flags); if (!eol || (c != __DISABLED_CHAR)) { - if (put_user(c, b++)) { + if (tty_put_user(tty, c, b++)) { retval = -EFAULT; b--; break; } nr--; } - if (eol) + if (eol) { + tty_audit_push(tty); break; + } } if (retval) break; @@ -1538,7 +1550,8 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol else tty->minimum_to_wake = 1; } - if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS && + if (!tty_is_writelocked(tty) && + tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS && tty->driver->write_room(tty) > 0) mask |= POLLOUT | POLLWRNORM; return mask; diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 204deaa0de80..98dec380af49 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -42,19 +42,12 @@ #define PC 1 #define ATARI 2 -#define COBALT 3 /* select machine configuration */ #if defined(CONFIG_ATARI) # define MACH ATARI #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ -#define MACH PC -# if defined(CONFIG_COBALT) -# include <linux/cobalt-nvram.h> -# define MACH COBALT -# else -# define MACH PC -# endif +# define MACH PC #else # error Cannot build nvram driver for this machine configuration. #endif @@ -76,18 +69,6 @@ #endif -#if MACH == COBALT - -#define CHECK_DRIVER_INIT() 1 - -#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE) - -#define mach_check_checksum cobalt_check_checksum -#define mach_set_checksum cobalt_set_checksum -#define mach_proc_infos cobalt_proc_infos - -#endif - #if MACH == ATARI /* Special parameters for RTC in Atari machines */ @@ -604,177 +585,6 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len, #endif /* MACH == PC */ -#if MACH == COBALT - -/* the cobalt CMOS has a wider range of its checksum */ -static int cobalt_check_checksum(void) -{ - int i; - unsigned short sum = 0; - unsigned short expect; - - for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) { - if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1))) - continue; - - sum += __nvram_read_byte(i); - } - expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 | - __nvram_read_byte(COBT_CMOS_CHECKSUM+1); - return ((sum & 0xffff) == expect); -} - -static void cobalt_set_checksum(void) -{ - int i; - unsigned short sum = 0; - - for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) { - if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1))) - continue; - - sum += __nvram_read_byte(i); - } - - __nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM); - __nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1); -} - -#ifdef CONFIG_PROC_FS - -static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len, - off_t *begin, off_t offset, int size) -{ - int i; - unsigned int checksum; - unsigned int flags; - char sernum[14]; - char *key = "cNoEbTaWlOtR!"; - unsigned char bto_csum; - - spin_lock_irq(&rtc_lock); - checksum = __nvram_check_checksum(); - spin_unlock_irq(&rtc_lock); - - PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not "); - - flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8 - | nvram[COBT_CMOS_FLAG_BYTE_1]; - - PRINT_PROC("Console: %s\n", - flags & COBT_CMOS_CONSOLE_FLAG ? "on": "off"); - - PRINT_PROC("Firmware Debug Messages: %s\n", - flags & COBT_CMOS_DEBUG_FLAG ? "on": "off"); - - PRINT_PROC("Auto Prompt: %s\n", - flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off"); - - PRINT_PROC("Shutdown Status: %s\n", - flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty"); - - PRINT_PROC("Hardware Probe: %s\n", - flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full"); - - PRINT_PROC("System Fault: %sdetected\n", - flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not "); - - PRINT_PROC("Panic on OOPS: %s\n", - flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no"); - - PRINT_PROC("Delayed Cache Initialization: %s\n", - flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no"); - - PRINT_PROC("Show Logo at Boot: %s\n", - flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes"); - - PRINT_PROC("Boot Method: "); - switch (nvram[COBT_CMOS_BOOT_METHOD]) { - case COBT_CMOS_BOOT_METHOD_DISK: - PRINT_PROC("disk\n"); - break; - - case COBT_CMOS_BOOT_METHOD_ROM: - PRINT_PROC("rom\n"); - break; - - case COBT_CMOS_BOOT_METHOD_NET: - PRINT_PROC("net\n"); - break; - - default: - PRINT_PROC("unknown\n"); - break; - } - - PRINT_PROC("Primary Boot Device: %d:%d\n", - nvram[COBT_CMOS_BOOT_DEV0_MAJ], - nvram[COBT_CMOS_BOOT_DEV0_MIN] ); - PRINT_PROC("Secondary Boot Device: %d:%d\n", - nvram[COBT_CMOS_BOOT_DEV1_MAJ], - nvram[COBT_CMOS_BOOT_DEV1_MIN] ); - PRINT_PROC("Tertiary Boot Device: %d:%d\n", - nvram[COBT_CMOS_BOOT_DEV2_MAJ], - nvram[COBT_CMOS_BOOT_DEV2_MIN] ); - - PRINT_PROC("Uptime: %d\n", - nvram[COBT_CMOS_UPTIME_0] << 24 | - nvram[COBT_CMOS_UPTIME_1] << 16 | - nvram[COBT_CMOS_UPTIME_2] << 8 | - nvram[COBT_CMOS_UPTIME_3]); - - PRINT_PROC("Boot Count: %d\n", - nvram[COBT_CMOS_BOOTCOUNT_0] << 24 | - nvram[COBT_CMOS_BOOTCOUNT_1] << 16 | - nvram[COBT_CMOS_BOOTCOUNT_2] << 8 | - nvram[COBT_CMOS_BOOTCOUNT_3]); - - /* 13 bytes of serial num */ - for (i=0 ; i<13 ; i++) { - sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i]; - } - sernum[13] = '\0'; - - checksum = 0; - for (i=0 ; i<13 ; i++) { - checksum += sernum[i] ^ key[i]; - } - checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff; - - PRINT_PROC("Serial Number: %s", sernum); - if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) { - PRINT_PROC(" (invalid checksum)"); - } - PRINT_PROC("\n"); - - PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ], - nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]); - - PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0], - nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2], - nvram[COBT_CMOS_BTO_IP_3]); - bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1] - + nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3]; - if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) { - PRINT_PROC(" (invalid checksum)"); - } - PRINT_PROC("\n"); - - if (flags & COBT_CMOS_VERSION_FLAG - && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) { - PRINT_PROC("BTO Code: 0x%x\n", - nvram[COBT_CMOS_BTO_CODE_0] << 24 | - nvram[COBT_CMOS_BTO_CODE_1] << 16 | - nvram[COBT_CMOS_BTO_CODE_2] << 8 | - nvram[COBT_CMOS_BTO_CODE_3]); - } - - return 1; -} -#endif /* CONFIG_PROC_FS */ - -#endif /* MACH == COBALT */ - #if MACH == ATARI static int diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index a3fd7e7ba5a9..0270080ff0c0 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1702,7 +1702,8 @@ static int rp_write(struct tty_struct *tty, if (count <= 0 || rocket_paranoia_check(info, "rp_write")) return 0; - mutex_lock_interruptible(&info->write_mtx); + if (mutex_lock_interruptible(&info->write_mtx)) + return -ERESTARTSYS; #ifdef ROCKET_DEBUG_WRITE printk(KERN_INFO "rp_write %d chars...", count); diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 20380a2c4dee..22cf7aa56cc4 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -1159,7 +1159,8 @@ static void rtc_dropped_irq(unsigned long data) spin_unlock_irq(&rtc_lock); - printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); + if (printk_ratelimit()) + printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); /* Now we have new data */ wake_up_interruptible(&rtc_wait); diff --git a/drivers/char/selection.c b/drivers/char/selection.c index a69f094d1ed3..d63f5ccc29e6 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -20,6 +20,7 @@ #include <asm/uaccess.h> +#include <linux/kbd_kern.h> #include <linux/vt_kern.h> #include <linux/consolemap.h> #include <linux/selection.h> @@ -34,6 +35,7 @@ extern void poke_blanked_console(void); /* Variables for selection control. */ /* Use a dynamic buffer, instead of static (Dec 1994) */ struct vc_data *sel_cons; /* must not be deallocated */ +static int use_unicode; static volatile int sel_start = -1; /* cleared by clear_selection */ static int sel_end; static int sel_buffer_lth; @@ -54,10 +56,11 @@ static inline void highlight_pointer(const int where) complement_pos(sel_cons, where); } -static unsigned char +static u16 sel_pos(int n) { - return inverse_translate(sel_cons, screen_glyph(sel_cons, n)); + return inverse_translate(sel_cons, screen_glyph(sel_cons, n), + use_unicode); } /* remove the current selection highlight, if any, @@ -86,8 +89,8 @@ static u32 inwordLut[8]={ 0xFF7FFFFF /* latin-1 accented letters, not division sign */ }; -static inline int inword(const unsigned char c) { - return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1; +static inline int inword(const u16 c) { + return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1); } /* set inwordLut contents. Invoked by ioctl(). */ @@ -108,13 +111,36 @@ static inline unsigned short limit(const unsigned short v, const unsigned short return (v > u) ? u : v; } +/* stores the char in UTF8 and returns the number of bytes used (1-3) */ +static int store_utf8(u16 c, char *p) +{ + if (c < 0x80) { + /* 0******* */ + p[0] = c; + return 1; + } else if (c < 0x800) { + /* 110***** 10****** */ + p[0] = 0xc0 | (c >> 6); + p[1] = 0x80 | (c & 0x3f); + return 2; + } else { + /* 1110**** 10****** 10****** */ + p[0] = 0xe0 | (c >> 12); + p[1] = 0x80 | ((c >> 6) & 0x3f); + p[2] = 0x80 | (c & 0x3f); + return 3; + } +} + /* set the current selection. Invoked by ioctl() or by kernel code. */ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) { struct vc_data *vc = vc_cons[fg_console].d; int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; - int i, ps, pe; + int i, ps, pe, multiplier; + u16 c; + struct kbd_struct *kbd = kbd_table + fg_console; poke_blanked_console(); @@ -158,6 +184,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t clear_selection(); sel_cons = vc_cons[fg_console].d; } + use_unicode = kbd && kbd->kbdmode == VC_UNICODE; switch (sel_mode) { @@ -240,7 +267,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t sel_end = new_sel_end; /* Allocate a new buffer before freeing the old one ... */ - bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL); + multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ + bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); @@ -251,8 +279,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t obp = bp; for (i = sel_start; i <= sel_end; i += 2) { - *bp = sel_pos(i); - if (!isspace(*bp++)) + c = sel_pos(i); + if (use_unicode) + bp += store_utf8(c, bp); + else + *bp++ = c; + if (!isspace(c)) obp = bp; if (! ((i + 2) % vc->vc_size_row)) { /* strip trailing blanks from line and add newline, diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 3ef593a9015f..73037a4d3c50 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -885,53 +885,6 @@ found: return IRQ_HANDLED; } -/* External camera command (exported to the motion eye v4l driver) */ -int sonypi_camera_command(int command, u8 value) -{ - if (!camera) - return -EIO; - - mutex_lock(&sonypi_device.lock); - - switch (command) { - case SONYPI_COMMAND_SETCAMERA: - if (value) - sonypi_camera_on(); - else - sonypi_camera_off(); - break; - case SONYPI_COMMAND_SETCAMERABRIGHTNESS: - sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value); - break; - case SONYPI_COMMAND_SETCAMERACONTRAST: - sonypi_set(SONYPI_CAMERA_CONTRAST, value); - break; - case SONYPI_COMMAND_SETCAMERAHUE: - sonypi_set(SONYPI_CAMERA_HUE, value); - break; - case SONYPI_COMMAND_SETCAMERACOLOR: - sonypi_set(SONYPI_CAMERA_COLOR, value); - break; - case SONYPI_COMMAND_SETCAMERASHARPNESS: - sonypi_set(SONYPI_CAMERA_SHARPNESS, value); - break; - case SONYPI_COMMAND_SETCAMERAPICTURE: - sonypi_set(SONYPI_CAMERA_PICTURE, value); - break; - case SONYPI_COMMAND_SETCAMERAAGC: - sonypi_set(SONYPI_CAMERA_AGC, value); - break; - default: - printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n", - command); - break; - } - mutex_unlock(&sonypi_device.lock); - return 0; -} - -EXPORT_SYMBOL(sonypi_camera_command); - static int sonypi_misc_fasync(int fd, struct file *filp, int on) { int retval; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f02a0795983f..f53e51ddb9d7 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -160,8 +160,6 @@ typedef struct _DMABUFFERENTRY #define IO_PIN_SHUTDOWN_LIMIT 100 -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - struct _input_signal_events { int ri_up; int ri_down; @@ -3064,12 +3062,6 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__, tty->driver->name ); - /* just return if nothing has changed */ - if ((tty->termios->c_cflag == old_termios->c_cflag) - && (RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - mgsl_change_params(info); /* Handle transition to B0 status */ diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 02b49bc00028..428b514201f4 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -144,8 +144,6 @@ MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable") /* * tty support and callbacks */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); @@ -823,12 +821,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) DBGINFO(("%s set_termios\n", tty->driver->name)); - /* just return if nothing has changed */ - if ((tty->termios->c_cflag == old_termios->c_cflag) - && (RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - change_params(info); /* Handle transition to B0 status */ diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ef93d055bdd7..a65407b32079 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -135,8 +135,6 @@ typedef struct _SCADESC_EX #define IO_PIN_SHUTDOWN_LIMIT 100 -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - struct _input_signal_events { int ri_up; int ri_down; @@ -927,12 +925,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__, tty->driver->name ); - /* just return if nothing has changed */ - if ((tty->termios->c_cflag == old_termios->c_cflag) - && (RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - change_params(info); /* Handle transition to B0 status */ diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index dc4e1ff7f56f..8f3f7620f95a 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -2,11 +2,9 @@ # TPM device configuration # -menu "TPM devices" - depends on HAS_IOMEM - -config TCG_TPM +menuconfig TCG_TPM tristate "TPM Hardware Support" + depends on HAS_IOMEM depends on EXPERIMENTAL ---help--- If you have a TPM security chip in your system, which @@ -21,9 +19,11 @@ config TCG_TPM Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI and CONFIG_PNPACPI. +if TCG_TPM + config TCG_TIS tristate "TPM Interface Specification 1.2 Interface" - depends on TCG_TPM && PNPACPI + depends on PNPACPI ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification say Yes and it will be accessible @@ -32,7 +32,7 @@ config TCG_TIS config TCG_NSC tristate "National Semiconductor TPM Interface" - depends on TCG_TPM && PNPACPI + depends on PNPACPI ---help--- If you have a TPM security chip from National Semiconductor say Yes and it will be accessible from within Linux. To @@ -41,7 +41,6 @@ config TCG_NSC config TCG_ATMEL tristate "Atmel TPM Interface" - depends on TCG_TPM ---help--- If you have a TPM security chip from Atmel say Yes and it will be accessible from within Linux. To compile this driver @@ -49,7 +48,7 @@ config TCG_ATMEL config TCG_INFINEON tristate "Infineon Technologies TPM Interface" - depends on TCG_TPM && PNPACPI + depends on PNPACPI ---help--- If you have a TPM security chip from Infineon Technologies (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it @@ -59,5 +58,4 @@ config TCG_INFINEON Further information on this driver and the supported hardware can be found at http://www.prosec.rub.de/tpm -endmenu - +endif # TCG_TPM diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c new file mode 100644 index 000000000000..d222012c1b0c --- /dev/null +++ b/drivers/char/tty_audit.c @@ -0,0 +1,345 @@ +/* + * Creating audit events from TTY input. + * + * Copyright (C) 2007 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 of the GNU General + * Public License v.2. + * + * Authors: Miloslav Trmac <mitr@redhat.com> + */ + +#include <linux/audit.h> +#include <linux/file.h> +#include <linux/tty.h> + +struct tty_audit_buf { + atomic_t count; + struct mutex mutex; /* Protects all data below */ + int major, minor; /* The TTY which the data is from */ + unsigned icanon:1; + size_t valid; + unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ +}; + +static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, + int icanon) +{ + struct tty_audit_buf *buf; + + buf = kmalloc(sizeof (*buf), GFP_KERNEL); + if (!buf) + goto err; + if (PAGE_SIZE != N_TTY_BUF_SIZE) + buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); + else + buf->data = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!buf->data) + goto err_buf; + atomic_set(&buf->count, 1); + mutex_init(&buf->mutex); + buf->major = major; + buf->minor = minor; + buf->icanon = icanon; + buf->valid = 0; + return buf; + +err_buf: + kfree(buf); +err: + return NULL; +} + +static void tty_audit_buf_free(struct tty_audit_buf *buf) +{ + WARN_ON(buf->valid != 0); + if (PAGE_SIZE != N_TTY_BUF_SIZE) + kfree(buf->data); + else + free_page((unsigned long)buf->data); + kfree(buf); +} + +static void tty_audit_buf_put(struct tty_audit_buf *buf) +{ + if (atomic_dec_and_test(&buf->count)) + tty_audit_buf_free(buf); +} + +/** + * tty_audit_buf_push - Push buffered data out + * + * Generate an audit message from the contents of @buf, which is owned by + * @tsk with @loginuid. @buf->mutex must be locked. + */ +static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, + struct tty_audit_buf *buf) +{ + struct audit_buffer *ab; + + if (buf->valid == 0) + return; + if (audit_enabled == 0) + return; + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); + if (ab) { + char name[sizeof(tsk->comm)]; + + audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d " + "minor=%d comm=", tsk->pid, tsk->uid, + loginuid, buf->major, buf->minor); + get_task_comm(name, tsk); + audit_log_untrustedstring(ab, name); + audit_log_format(ab, " data="); + audit_log_n_untrustedstring(ab, buf->valid, buf->data); + audit_log_end(ab); + } + buf->valid = 0; +} + +/** + * tty_audit_buf_push_current - Push buffered data out + * + * Generate an audit message from the contents of @buf, which is owned by + * the current task. @buf->mutex must be locked. + */ +static void tty_audit_buf_push_current(struct tty_audit_buf *buf) +{ + tty_audit_buf_push(current, audit_get_loginuid(current->audit_context), + buf); +} + +/** + * tty_audit_exit - Handle a task exit + * + * Make sure all buffered data is written out and deallocate the buffer. + * Only needs to be called if current->signal->tty_audit_buf != %NULL. + */ +void tty_audit_exit(void) +{ + struct tty_audit_buf *buf; + + spin_lock_irq(¤t->sighand->siglock); + buf = current->signal->tty_audit_buf; + current->signal->tty_audit_buf = NULL; + spin_unlock_irq(¤t->sighand->siglock); + if (!buf) + return; + + mutex_lock(&buf->mutex); + tty_audit_buf_push_current(buf); + mutex_unlock(&buf->mutex); + + tty_audit_buf_put(buf); +} + +/** + * tty_audit_fork - Copy TTY audit state for a new task + * + * Set up TTY audit state in @sig from current. @sig needs no locking. + */ +void tty_audit_fork(struct signal_struct *sig) +{ + spin_lock_irq(¤t->sighand->siglock); + sig->audit_tty = current->signal->audit_tty; + spin_unlock_irq(¤t->sighand->siglock); + sig->tty_audit_buf = NULL; +} + +/** + * tty_audit_push_task - Flush task's pending audit data + */ +void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) +{ + struct tty_audit_buf *buf; + + spin_lock_irq(&tsk->sighand->siglock); + buf = tsk->signal->tty_audit_buf; + if (buf) + atomic_inc(&buf->count); + spin_unlock_irq(&tsk->sighand->siglock); + if (!buf) + return; + + mutex_lock(&buf->mutex); + tty_audit_buf_push(tsk, loginuid, buf); + mutex_unlock(&buf->mutex); + + tty_audit_buf_put(buf); +} + +/** + * tty_audit_buf_get - Get an audit buffer. + * + * Get an audit buffer for @tty, allocate it if necessary. Return %NULL + * if TTY auditing is disabled or out of memory. Otherwise, return a new + * reference to the buffer. + */ +static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) +{ + struct tty_audit_buf *buf, *buf2; + + buf = NULL; + buf2 = NULL; + spin_lock_irq(¤t->sighand->siglock); + if (likely(!current->signal->audit_tty)) + goto out; + buf = current->signal->tty_audit_buf; + if (buf) { + atomic_inc(&buf->count); + goto out; + } + spin_unlock_irq(¤t->sighand->siglock); + + buf2 = tty_audit_buf_alloc(tty->driver->major, + tty->driver->minor_start + tty->index, + tty->icanon); + if (buf2 == NULL) { + audit_log_lost("out of memory in TTY auditing"); + return NULL; + } + + spin_lock_irq(¤t->sighand->siglock); + if (!current->signal->audit_tty) + goto out; + buf = current->signal->tty_audit_buf; + if (!buf) { + current->signal->tty_audit_buf = buf2; + buf = buf2; + buf2 = NULL; + } + atomic_inc(&buf->count); + /* Fall through */ + out: + spin_unlock_irq(¤t->sighand->siglock); + if (buf2) + tty_audit_buf_free(buf2); + return buf; +} + +/** + * tty_audit_add_data - Add data for TTY auditing. + * + * Audit @data of @size from @tty, if necessary. + */ +void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, + size_t size) +{ + struct tty_audit_buf *buf; + int major, minor; + + if (unlikely(size == 0)) + return; + + buf = tty_audit_buf_get(tty); + if (!buf) + return; + + mutex_lock(&buf->mutex); + major = tty->driver->major; + minor = tty->driver->minor_start + tty->index; + if (buf->major != major || buf->minor != minor + || buf->icanon != tty->icanon) { + tty_audit_buf_push_current(buf); + buf->major = major; + buf->minor = minor; + buf->icanon = tty->icanon; + } + do { + size_t run; + + run = N_TTY_BUF_SIZE - buf->valid; + if (run > size) + run = size; + memcpy(buf->data + buf->valid, data, run); + buf->valid += run; + data += run; + size -= run; + if (buf->valid == N_TTY_BUF_SIZE) + tty_audit_buf_push_current(buf); + } while (size != 0); + mutex_unlock(&buf->mutex); + tty_audit_buf_put(buf); +} + +/** + * tty_audit_push - Push buffered data out + * + * Make sure no audit data is pending for @tty on the current process. + */ +void tty_audit_push(struct tty_struct *tty) +{ + struct tty_audit_buf *buf; + + spin_lock_irq(¤t->sighand->siglock); + if (likely(!current->signal->audit_tty)) { + spin_unlock_irq(¤t->sighand->siglock); + return; + } + buf = current->signal->tty_audit_buf; + if (buf) + atomic_inc(&buf->count); + spin_unlock_irq(¤t->sighand->siglock); + + if (buf) { + int major, minor; + + major = tty->driver->major; + minor = tty->driver->minor_start + tty->index; + mutex_lock(&buf->mutex); + if (buf->major == major && buf->minor == minor) + tty_audit_buf_push_current(buf); + mutex_unlock(&buf->mutex); + tty_audit_buf_put(buf); + } +} + +/** + * tty_audit_opening - A TTY is being opened. + * + * As a special hack, tasks that close all their TTYs and open new ones + * are assumed to be system daemons (e.g. getty) and auditing is + * automatically disabled for them. + */ +void tty_audit_opening(void) +{ + int disable; + + disable = 1; + spin_lock_irq(¤t->sighand->siglock); + if (current->signal->audit_tty == 0) + disable = 0; + spin_unlock_irq(¤t->sighand->siglock); + if (!disable) + return; + + task_lock(current); + if (current->files) { + struct fdtable *fdt; + unsigned i; + + /* + * We don't take a ref to the file, so we must hold ->file_lock + * instead. + */ + spin_lock(¤t->files->file_lock); + fdt = files_fdtable(current->files); + for (i = 0; i < fdt->max_fds; i++) { + struct file *filp; + + filp = fcheck_files(current->files, i); + if (filp && is_tty(filp)) { + disable = 0; + break; + } + } + spin_unlock(¤t->files->file_lock); + } + task_unlock(current); + if (!disable) + return; + + spin_lock_irq(¤t->sighand->siglock); + current->signal->audit_tty = 0; + spin_unlock_irq(¤t->sighand->siglock); +} diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a96f26a63fa2..de37ebc3a4cf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1503,6 +1503,15 @@ int tty_hung_up_p(struct file * filp) EXPORT_SYMBOL(tty_hung_up_p); +/** + * is_tty - checker whether file is a TTY + */ +int is_tty(struct file *filp) +{ + return filp->f_op->read == tty_read + || filp->f_op->read == hung_up_tty_read; +} + static void session_clear_tty(struct pid *session) { struct task_struct *p; @@ -1726,6 +1735,23 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, return i; } +void tty_write_unlock(struct tty_struct *tty) +{ + mutex_unlock(&tty->atomic_write_lock); + wake_up_interruptible(&tty->write_wait); +} + +int tty_write_lock(struct tty_struct *tty, int ndelay) +{ + if (!mutex_trylock(&tty->atomic_write_lock)) { + if (ndelay) + return -EAGAIN; + if (mutex_lock_interruptible(&tty->atomic_write_lock)) + return -ERESTARTSYS; + } + return 0; +} + /* * Split writes up in sane blocksizes to avoid * denial-of-service type attacks @@ -1737,13 +1763,12 @@ static inline ssize_t do_tty_write( const char __user *buf, size_t count) { - ssize_t ret = 0, written = 0; + ssize_t ret, written = 0; unsigned int chunk; - /* FIXME: O_NDELAY ... */ - if (mutex_lock_interruptible(&tty->atomic_write_lock)) { - return -ERESTARTSYS; - } + ret = tty_write_lock(tty, file->f_flags & O_NDELAY); + if (ret < 0) + return ret; /* * We chunk up writes into a temporary buffer. This @@ -1776,8 +1801,8 @@ static inline ssize_t do_tty_write( buf = kmalloc(chunk, GFP_KERNEL); if (!buf) { - mutex_unlock(&tty->atomic_write_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } kfree(tty->write_buf); tty->write_cnt = chunk; @@ -1812,7 +1837,8 @@ static inline ssize_t do_tty_write( inode->i_mtime = current_fs_time(inode->i_sb); ret = written; } - mutex_unlock(&tty->atomic_write_lock); +out: + tty_write_unlock(tty); return ret; } @@ -2016,11 +2042,9 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*ltp_loc) { - ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios), - GFP_KERNEL); + ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); if (!ltp) goto free_mem_out; - memset(ltp, 0, sizeof(struct ktermios)); } if (driver->type == TTY_DRIVER_TYPE_PTY) { @@ -2049,11 +2073,9 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*o_ltp_loc) { - o_ltp = (struct ktermios *) - kmalloc(sizeof(struct ktermios), GFP_KERNEL); + o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); if (!o_ltp) goto free_mem_out; - memset(o_ltp, 0, sizeof(struct ktermios)); } /* @@ -2660,6 +2682,7 @@ got_driver: __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); mutex_unlock(&tty_mutex); + tty_audit_opening(); return 0; } @@ -2722,8 +2745,10 @@ static int ptmx_open(struct inode * inode, struct file * filp) check_tty_count(tty, "tty_open"); retval = ptm_driver->open(tty, filp); - if (!retval) + if (!retval) { + tty_audit_opening(); return 0; + } out1: release_dev(filp); return retval; @@ -3163,14 +3188,13 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) static int send_break(struct tty_struct *tty, unsigned int duration) { - if (mutex_lock_interruptible(&tty->atomic_write_lock)) + if (tty_write_lock(tty, 0) < 0) return -EINTR; tty->driver->break_ctl(tty, -1); - if (!signal_pending(current)) { + if (!signal_pending(current)) msleep_interruptible(duration); - } tty->driver->break_ctl(tty, 0); - mutex_unlock(&tty->atomic_write_lock); + tty_write_unlock(tty); if (signal_pending(current)) return -EINTR; return 0; @@ -3739,9 +3763,8 @@ struct tty_driver *alloc_tty_driver(int lines) { struct tty_driver *driver; - driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL); + driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); if (driver) { - memset(driver, 0, sizeof(struct tty_driver)); driver->magic = TTY_DRIVER_MAGIC; driver->num = lines; /* later we'll move allocation of tables here */ diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index fd471cb3338f..3423e9ee6481 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -52,8 +52,6 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) { - DECLARE_WAITQUEUE(wait, current); - #ifdef TTY_DEBUG_WAIT_UNTIL_SENT char buf[64]; @@ -61,26 +59,13 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) #endif if (!tty->driver->chars_in_buffer) return; - add_wait_queue(&tty->write_wait, &wait); if (!timeout) timeout = MAX_SCHEDULE_TIMEOUT; - do { -#ifdef TTY_DEBUG_WAIT_UNTIL_SENT - printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf), - tty->driver->chars_in_buffer(tty)); -#endif - set_current_state(TASK_INTERRUPTIBLE); - if (signal_pending(current)) - goto stop_waiting; - if (!tty->driver->chars_in_buffer(tty)) - break; - timeout = schedule_timeout(timeout); - } while (timeout); + if (wait_event_interruptible_timeout(tty->write_wait, + !tty->driver->chars_in_buffer(tty), timeout)) + return; if (tty->driver->wait_until_sent) tty->driver->wait_until_sent(tty, timeout); -stop_waiting: - set_current_state(TASK_RUNNING); - remove_wait_queue(&tty->write_wait, &wait); } EXPORT_SYMBOL(tty_wait_until_sent); @@ -276,13 +261,12 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed termios->c_cflag |= (baud_bits[i] << IBSHIFT); ifound = i; } - } - while(++i < n_baud_table); + } while (++i < n_baud_table); if (ofound == -1) termios->c_cflag |= BOTHER; /* Set exact input bits only if the input and output differ or the user already did */ - if (ifound == -1 && (ibaud != obaud || ibinput)) + if (ifound == -1 && (ibaud != obaud || ibinput)) termios->c_cflag |= (BOTHER << IBSHIFT); } @@ -575,7 +559,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) return -EFAULT; mutex_lock(&tty->termios_mutex); - termios = *tty->termios; + termios = *tty->termios; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); @@ -667,7 +651,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) return 0; } - if (mutex_lock_interruptible(&tty->atomic_write_lock)) + if (tty_write_lock(tty, 0) < 0) return -ERESTARTSYS; if (was_stopped) @@ -675,7 +659,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) tty->driver->write(tty, &ch, 1); if (was_stopped) stop_tty(tty); - mutex_unlock(&tty->atomic_write_lock); + tty_write_unlock(tty); return 0; } diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 0cea8d4907df..e5ed09192be8 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -19,18 +19,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/platform_device.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> -#include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/types.h> -#include <asm/cpu.h> #include <asm/io.h> #include <asm/vr41xx/giu.h> #include <asm/vr41xx/irq.h> @@ -44,18 +43,6 @@ static int major; /* default is dynamic major device number */ module_param(major, int, 0); MODULE_PARM_DESC(major, "Major device number"); -#define GIU_TYPE1_START 0x0b000100UL -#define GIU_TYPE1_SIZE 0x20UL - -#define GIU_TYPE2_START 0x0f000140UL -#define GIU_TYPE2_SIZE 0x20UL - -#define GIU_TYPE3_START 0x0f000140UL -#define GIU_TYPE3_SIZE 0x28UL - -#define GIU_PULLUPDOWN_START 0x0b0002e0UL -#define GIU_PULLUPDOWN_SIZE 0x04UL - #define GIUIOSELL 0x00 #define GIUIOSELH 0x02 #define GIUPIODL 0x04 @@ -89,8 +76,6 @@ MODULE_PARM_DESC(major, "Major device number"); #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 static spinlock_t giu_lock; -static struct resource *giu_resource1; -static struct resource *giu_resource2; static unsigned long giu_flags; static unsigned int giu_nr_pins; @@ -234,7 +219,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ giu_set(GIUINTHTSELL, mask); else giu_clear(GIUINTHTSELL, mask); - if (current_cpu_data.cputype == CPU_VR4133) { + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { switch (trigger) { case IRQ_TRIGGER_EDGE_FALLING: giu_set(GIUFEDGEINHL, mask); @@ -269,7 +254,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ giu_set(GIUINTHTSELH, mask); else giu_clear(GIUINTHTSELH, mask); - if (current_cpu_data.cputype == CPU_VR4133) { + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { switch (trigger) { case IRQ_TRIGGER_EDGE_FALLING: giu_set(GIUFEDGEINHH, mask); @@ -298,7 +283,6 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ giu_write(GIUINTSTATH, mask); } } - EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) @@ -321,7 +305,6 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) giu_write(GIUINTSTATH, mask); } } - EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) @@ -350,7 +333,6 @@ gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) return GPIO_DATA_LOW; } - EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) @@ -388,7 +370,6 @@ int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) return 0; } - EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) @@ -438,7 +419,6 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) return 0; } - EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) @@ -477,7 +457,6 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) return 0; } - EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, @@ -596,61 +575,40 @@ static const struct file_operations gpio_fops = { static int __devinit giu_probe(struct platform_device *dev) { - unsigned long start, size, flags = 0; - unsigned int nr_pins = 0, trigger, i, pin; - struct resource *res1, *res2 = NULL; - void *base; + struct resource *res; + unsigned int trigger, i, pin; struct irq_chip *chip; - int retval; - - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: - start = GIU_TYPE1_START; - size = GIU_TYPE1_SIZE; - flags = GPIO_HAS_PULLUPDOWN_IO; - nr_pins = 50; + int irq, retval; + + switch (dev->id) { + case GPIO_50PINS_PULLUPDOWN: + giu_flags = GPIO_HAS_PULLUPDOWN_IO; + giu_nr_pins = 50; break; - case CPU_VR4122: - case CPU_VR4131: - start = GIU_TYPE2_START; - size = GIU_TYPE2_SIZE; - nr_pins = 36; + case GPIO_36PINS: + giu_nr_pins = 36; break; - case CPU_VR4133: - start = GIU_TYPE3_START; - size = GIU_TYPE3_SIZE; - flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; - nr_pins = 48; + case GPIO_48PINS_EDGE_SELECT: + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; + giu_nr_pins = 48; break; default: + printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); return -ENODEV; } - res1 = request_mem_region(start, size, "GIU"); - if (res1 == NULL) + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) return -EBUSY; - base = ioremap(start, size); - if (base == NULL) { - release_resource(res1); + giu_base = ioremap(res->start, res->end - res->start + 1); + if (!giu_base) return -ENOMEM; - } - - if (flags & GPIO_HAS_PULLUPDOWN_IO) { - res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU"); - if (res2 == NULL) { - iounmap(base); - release_resource(res1); - return -EBUSY; - } - } retval = register_chrdev(major, "GIU", &gpio_fops); if (retval < 0) { - iounmap(base); - release_resource(res1); - release_resource(res2); + iounmap(giu_base); + giu_base = NULL; return retval; } @@ -660,11 +618,6 @@ static int __devinit giu_probe(struct platform_device *dev) } spin_lock_init(&giu_lock); - giu_base = base; - giu_resource1 = res1; - giu_resource2 = res2; - giu_flags = flags; - giu_nr_pins = nr_pins; giu_write(GIUINTENL, 0); giu_write(GIUINTENH, 0); @@ -685,22 +638,23 @@ static int __devinit giu_probe(struct platform_device *dev) } - return cascade_irq(GIUINT_IRQ, giu_get_irq); + irq = platform_get_irq(dev, 0); + if (irq < 0 || irq >= NR_IRQS) + return -EBUSY; + + return cascade_irq(irq, giu_get_irq); } static int __devexit giu_remove(struct platform_device *dev) { - iounmap(giu_base); - - release_resource(giu_resource1); - if (giu_flags & GPIO_HAS_PULLUPDOWN_IO) - release_resource(giu_resource2); + if (giu_base) { + iounmap(giu_base); + giu_base = NULL; + } return 0; } -static struct platform_device *giu_platform_device; - static struct platform_driver giu_device_driver = { .probe = giu_probe, .remove = __devexit_p(giu_remove), @@ -712,30 +666,12 @@ static struct platform_driver giu_device_driver = { static int __init vr41xx_giu_init(void) { - int retval; - - giu_platform_device = platform_device_alloc("GIU", -1); - if (!giu_platform_device) - return -ENOMEM; - - retval = platform_device_add(giu_platform_device); - if (retval < 0) { - platform_device_put(giu_platform_device); - return retval; - } - - retval = platform_driver_register(&giu_device_driver); - if (retval < 0) - platform_device_unregister(giu_platform_device); - - return retval; + return platform_driver_register(&giu_device_driver); } static void __exit vr41xx_giu_exit(void) { platform_driver_unregister(&giu_device_driver); - - platform_device_unregister(giu_platform_device); } module_init(vr41xx_giu_init); |