diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-08-11 11:19:20 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-11 11:19:20 +0200 |
commit | 8067794bec1cc5de1431102cf0a6a1c7ce75cd85 (patch) | |
tree | 2bfa0fba060d253bbd972282b29a3d60c3e7cb7f /drivers/char | |
parent | 7ab6af7ab69df8c9c5fbc380004fb81187742096 (diff) | |
parent | 796aadeb1b2db9b5d463946766c5bbfd7717158c (diff) |
Merge branch 'linus' into x86/x2apic
Conflicts:
arch/x86/kernel/genapic_64.c
Manual merge:
arch/x86/kernel/genx2apic_uv_x.c
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/char')
50 files changed, 848 insertions, 1890 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 67b07576f8b..caff85149b9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -8,7 +8,7 @@ config VT bool "Virtual terminal" if EMBEDDED depends on !S390 select INPUT - default y if !VIOCONS + default y ---help--- If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you @@ -36,6 +36,14 @@ config VT If unsure, say Y, or else you won't be able to do much with your new shiny Linux system :-) +config CONSOLE_TRANSLATIONS + depends on VT + default y + bool "Enable character translations in console" if EMBEDDED + ---help--- + This enables support for font mapping and Unicode translation + on virtual consoles. + config VT_CONSOLE bool "Support for console on virtual terminal" if EMBEDDED depends on VT @@ -578,11 +586,14 @@ config HVC_DRIVER It will automatically be selected if one of the back-end console drivers is selected. +config HVC_IRQ + bool config HVC_CONSOLE bool "pSeries Hypervisor Virtual Console support" depends on PPC_PSERIES select HVC_DRIVER + select HVC_IRQ help pSeries machines when partitioned support a hypervisor virtual console. This driver allows each pSeries partition to have a console @@ -593,6 +604,7 @@ config HVC_ISERIES depends on PPC_ISERIES default y select HVC_DRIVER + select HVC_IRQ help iSeries machines support a hypervisor virtual console. @@ -614,13 +626,18 @@ config HVC_XEN bool "Xen Hypervisor Console support" depends on XEN select HVC_DRIVER + select HVC_IRQ default y help Xen virtual console device driver config VIRTIO_CONSOLE - bool + tristate "Virtio console" + depends on VIRTIO select HVC_DRIVER + help + Virtio console for use with lguest and other hypervisors. + config HVCS tristate "IBM Hypervisor Virtual Console Server support" diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4b6e736cfa0..6850f6da757 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -12,8 +12,8 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-y += misc.o -obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ - consolemap_deftbl.o selection.o keyboard.o +obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o +obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o @@ -48,13 +48,13 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_HVC_BEAT) += hvc_beat.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o +obj-$(CONFIG_HVC_IRQ) += hvc_irq.o obj-$(CONFIG_HVC_XEN) += hvc_xen.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_MMTIMER) += mmtimer.o -obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_IBM_BSR) += bsr.o @@ -63,7 +63,6 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o obj-$(CONFIG_BFIN_OTP) += bfin-otp.o obj-$(CONFIG_PRINTER) += lp.o -obj-$(CONFIG_TIPAR) += tipar.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 3530ff417a5..6e763e3f5a8 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1254,7 +1254,7 @@ static int rs_break(struct tty_struct *tty, int break_state) unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_break")) - return; + return -EINVAL; local_irq_save(flags); if (break_state == -1) diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index fada6ddefba..c5e67a62395 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c @@ -20,10 +20,11 @@ #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/bcd.h> +#include <linux/smp_lock.h> +#include <linux/uaccess.h> +#include <linux/io.h> -#include <asm/uaccess.h> #include <asm/system.h> -#include <asm/io.h> #include <asm/rtc.h> #if defined(CONFIG_M32R) #include <asm/m32r.h> @@ -153,9 +154,7 @@ static unsigned char days_in_mo[] = /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ -static int -rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; @@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, struct rtc_time rtc_tm; memset(&rtc_tm, 0, sizeof (struct rtc_time)); + lock_kernel(); get_rtc_time(&rtc_tm); + unlock_kernel(); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) return -EFAULT; return 0; @@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, BIN_TO_BCD(mon); BIN_TO_BCD(yrs); + lock_kernel(); local_irq_save(flags); CMOS_WRITE(yrs, RTC_YEAR); CMOS_WRITE(mon, RTC_MONTH); @@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, CMOS_WRITE(min, RTC_MINUTES); CMOS_WRITE(sec, RTC_SECONDS); local_irq_restore(flags); + unlock_kernel(); /* Notice that at this point, the RTC is updated but * the kernel is still running with the old time. @@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) return -EFAULT; + lock_kernel(); tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); + unlock_kernel(); return 0; } default: @@ -282,7 +287,7 @@ get_rtc_status(char *buf) static const struct file_operations rtc_fops = { .owner = THIS_MODULE, - .ioctl = rtc_ioctl, + .unlocked_ioctl = rtc_ioctl, }; /* Probe for the chip by writing something to its RAM and try reading it back. */ diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 34275c6f1da..74e9cd81b5b 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -10,7 +10,7 @@ #include <linux/init.h> #include <linux/smp_lock.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/therm.h> diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 33c466a4888..ca7c72a486b 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -36,10 +36,10 @@ #include <linux/smp_lock.h> #include <linux/firmware.h> #include <linux/platform_device.h> +#include <linux/uaccess.h> /* For put_user and get_user */ #include <asm/atarihw.h> #include <asm/traps.h> -#include <asm/uaccess.h> /* For put_user and get_user */ #include <asm/dsp56k.h> @@ -303,10 +303,10 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co } } -static int dsp56k_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long dsp56k_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { - int dev = iminor(inode) & 0x0f; + int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; void __user *argp = (void __user *)arg; switch(dev) @@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if (len > DSP56K_MAX_BINARY_LENGTH) { return -EINVAL; } - + lock_kernel(); r = dsp56k_upload(bin, len); + unlock_kernel(); if (r < 0) { return r; } @@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, case DSP56K_SET_TX_WSIZE: if (arg > 4 || arg < 1) return -EINVAL; + lock_kernel(); dsp56k.tx_wsize = (int) arg; + unlock_kernel(); break; case DSP56K_SET_RX_WSIZE: if (arg > 4 || arg < 1) return -EINVAL; + lock_kernel(); dsp56k.rx_wsize = (int) arg; + unlock_kernel(); break; case DSP56K_HOST_FLAGS: { @@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if(get_user(out, &hf->out) < 0) return -EFAULT; + lock_kernel(); if ((dir & 0x1) && (out & 0x1)) dsp56k_host_interface.icr |= DSP56K_ICR_HF0; else if (dir & 0x1) @@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; - + unlock_kernel(); return put_user(status, &hf->status); } case DSP56K_HOST_CMD: if (arg > 31 || arg < 0) return -EINVAL; + lock_kernel(); dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | DSP56K_CVR_HC); + unlock_kernel(); break; default: return -EINVAL; @@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = { .owner = THIS_MODULE, .read = dsp56k_read, .write = dsp56k_write, - .ioctl = dsp56k_ioctl, + .unlocked_ioctl = dsp56k_ioctl, .open = dsp56k_open, .release = dsp56k_release, }; diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index d57ca3e4e53..34d15d54823 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -37,8 +37,8 @@ #include <linux/rtc.h> #include <linux/proc_fs.h> #include <linux/efi.h> +#include <linux/uaccess.h> -#include <asm/uaccess.h> #include <asm/system.h> #define EFI_RTC_VERSION "0.4" @@ -51,8 +51,8 @@ static DEFINE_SPINLOCK(efi_rtc_lock); -static int efi_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long efi_rtc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); #define is_leap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) @@ -146,9 +146,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) } } -static int -efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long efi_rtc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { efi_status_t status; @@ -175,13 +174,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; case RTC_RD_TIME: - + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.get_time(&eft, &cap); spin_unlock_irqrestore(&efi_rtc_lock,flags); - + unlock_kernel(); if (status != EFI_SUCCESS) { /* should never happen */ printk(KERN_ERR "efitime: can't read time\n"); @@ -203,11 +202,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, convert_to_efi_time(&wtime, &eft); + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.set_time(&eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); return status == EFI_SUCCESS ? 0 : -EINVAL; @@ -223,6 +224,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, convert_to_efi_time(&wtime, &eft); + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); /* * XXX Fixme: @@ -233,16 +235,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); return status == EFI_SUCCESS ? 0 : -EINVAL; case RTC_WKALM_RD: + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); if (status != EFI_SUCCESS) return -EINVAL; @@ -256,7 +261,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return copy_to_user(&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0; } - return -EINVAL; + return -ENOTTY; } /* @@ -265,8 +270,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * up things on a close. */ -static int -efi_rtc_open(struct inode *inode, struct file *file) +static int efi_rtc_open(struct inode *inode, struct file *file) { /* * nothing special to do here @@ -277,8 +281,7 @@ efi_rtc_open(struct inode *inode, struct file *file) return 0; } -static int -efi_rtc_close(struct inode *inode, struct file *file) +static int efi_rtc_close(struct inode *inode, struct file *file) { return 0; } @@ -289,13 +292,12 @@ efi_rtc_close(struct inode *inode, struct file *file) static const struct file_operations efi_rtc_fops = { .owner = THIS_MODULE, - .ioctl = efi_rtc_ioctl, + .unlocked_ioctl = efi_rtc_ioctl, .open = efi_rtc_open, .release = efi_rtc_close, }; -static struct miscdevice efi_rtc_dev= -{ +static struct miscdevice efi_rtc_dev= { EFI_RTC_MINOR, "efirtc", &efi_rtc_fops diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fb0a85a1eb3..b3f5dbc6d88 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp) return -ENXIO; } +#if 0 int hpet_unregister(struct hpet_task *tp) { struct hpet_dev *devp; @@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp) return 0; } +#endif /* 0 */ static ctl_table hpet_table[] = { { diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d625c..02aac104842 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -27,7 +27,6 @@ #include <linux/init.h> #include <linux/kbd_kern.h> #include <linux/kernel.h> -#include <linux/kref.h> #include <linux/kthread.h> #include <linux/list.h> #include <linux/module.h> @@ -75,23 +74,6 @@ static int hvc_init(void); static int sysrq_pressed; #endif -struct hvc_struct { - spinlock_t lock; - int index; - struct tty_struct *tty; - unsigned int count; - int do_wakeup; - char *outbuf; - int outbuf_size; - int n_outbuf; - uint32_t vtermno; - struct hv_ops *ops; - int irq_requested; - int irq; - struct list_head next; - struct kref kref; /* ref count & hvc_struct lifetime */ -}; - /* dynamic list of hvc_struct instances */ static LIST_HEAD(hvc_structs); @@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) return 0; } +EXPORT_SYMBOL_GPL(hvc_instantiate); /* Wake the sleeping khvcd */ -static void hvc_kick(void) +void hvc_kick(void) { hvc_kicked = 1; wake_up_process(hvc_task); } - -static int hvc_poll(struct hvc_struct *hp); - -/* - * NOTE: This API isn't used if the console adapter doesn't support interrupts. - * In this case the console is poll driven. - */ -static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) -{ - /* if hvc_poll request a repoll, then kick the hvcd thread */ - if (hvc_poll(dev_instance)) - hvc_kick(); - return IRQ_HANDLED; -} +EXPORT_SYMBOL_GPL(hvc_kick); static void hvc_unthrottle(struct tty_struct *tty) { @@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) { struct hvc_struct *hp; unsigned long flags; - int irq = 0; int rc = 0; /* Auto increments kref reference if found. */ @@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ hp->tty = tty; - /* Save for request_irq outside of spin_lock. */ - irq = hp->irq; - if (irq) - hp->irq_requested = 1; + + if (hp->ops->notifier_add) + rc = hp->ops->notifier_add(hp, hp->data); spin_unlock_irqrestore(&hp->lock, flags); - /* check error, fallback to non-irq */ - if (irq) - rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); + /* - * If the request_irq() fails and we return an error. The tty layer + * If the notifier fails we return an error. The tty layer * will call hvc_close() after a failed open but we don't want to clean * up there so we'll clean up here and clear out the previously set * tty fields and return the kref reference. @@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) if (rc) { spin_lock_irqsave(&hp->lock, flags); hp->tty = NULL; - hp->irq_requested = 0; spin_unlock_irqrestore(&hp->lock, flags); tty->driver_data = NULL; kref_put(&hp->kref, destroy_hvc_struct); @@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) static void hvc_close(struct tty_struct *tty, struct file * filp) { struct hvc_struct *hp; - int irq = 0; unsigned long flags; if (tty_hung_up_p(filp)) @@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->lock, flags); if (--hp->count == 0) { - if (hp->irq_requested) - irq = hp->irq; - hp->irq_requested = 0; + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); /* We are done with the tty pointer now. */ hp->tty = NULL; @@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) * waking periodically to check chars_in_buffer(). */ tty_wait_until_sent(tty, HVC_CLOSE_WAIT); - - if (irq) - free_irq(irq, hp); - } else { if (hp->count < 0) printk(KERN_ERR "hvc_close %X: oops, count is %d\n", @@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; unsigned long flags; - int irq = 0; int temp_open_count; if (!hp) @@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty) hp->count = 0; hp->n_outbuf = 0; hp->tty = NULL; - if (hp->irq_requested) - /* Saved for use outside of spin_lock. */ - irq = hp->irq; - hp->irq_requested = 0; + + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); + spin_unlock_irqrestore(&hp->lock, flags); - if (irq) - free_irq(irq, hp); + while(temp_open_count) { --temp_open_count; kref_put(&hp->kref, destroy_hvc_struct); @@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT; #define HVC_POLL_READ 0x00000001 #define HVC_POLL_WRITE 0x00000002 -static int hvc_poll(struct hvc_struct *hp) +int hvc_poll(struct hvc_struct *hp) { struct tty_struct *tty; int i, n, poll_mask = 0; @@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp) if (test_bit(TTY_THROTTLED, &tty->flags)) goto throttled; - /* If we aren't interrupt driven and aren't throttled, we always + /* If we aren't notifier driven and aren't throttled, we always * request a reschedule */ - if (hp->irq == 0) + if (!hp->irq_requested) poll_mask |= HVC_POLL_READ; /* Read data if any */ @@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp) return poll_mask; } +EXPORT_SYMBOL_GPL(hvc_poll); /* * This kthread is either polling or interrupt driven. This is determined by @@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = { .chars_in_buffer = hvc_chars_in_buffer, }; -struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, +struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, struct hv_ops *ops, int outbuf_size) { struct hvc_struct *hp; @@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, memset(hp, 0x00, sizeof(*hp)); hp->vtermno = vtermno; - hp->irq = irq; + hp->data = data; hp->ops = ops; hp->outbuf_size = outbuf_size; hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; @@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, return hp; } +EXPORT_SYMBOL_GPL(hvc_alloc); int __devexit hvc_remove(struct hvc_struct *hp) { diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 42ffb17e15d..9790201718a 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h @@ -6,7 +6,7 @@ * Ryan S. Arnold <rsa@us.ibm.com> * * hvc_console header information: - * moved here from include/asm-powerpc/hvconsole.h + * moved here from arch/powerpc/include/asm/hvconsole.h * and drivers/char/hvc_console.c * * This program is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ #ifndef HVC_CONSOLE_H #define HVC_CONSOLE_H +#include <linux/kref.h> /* * This is the max number of console adapters that can/will be found as @@ -42,24 +43,50 @@ */ #define HVC_ALLOC_TTY_ADAPTERS 8 +struct hvc_struct { + spinlock_t lock; + int index; + struct tty_struct *tty; + unsigned int count; + int do_wakeup; + char *outbuf; + int outbuf_size; + int n_outbuf; + uint32_t vtermno; + struct hv_ops *ops; + int irq_requested; + int data; + struct list_head next; + struct kref kref; /* ref count & hvc_struct lifetime */ +}; /* implemented by a low level driver */ struct hv_ops { int (*get_chars)(uint32_t vtermno, char *buf, int count); int (*put_chars)(uint32_t vtermno, const char *buf, int count); -}; -struct hvc_struct; + /* Callbacks for notification. Called in open and close */ + int (*notifier_add)(struct hvc_struct *hp, int irq); + void (*notifier_del)(struct hvc_struct *hp, int irq); +}; /* Register a vterm and a slot index for use as a console (console_init) */ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ -extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, struct hv_ops *ops, int outbuf_size); -/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ +/* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ extern int __devexit hvc_remove(struct hvc_struct *hp); +/* data available */ +int hvc_poll(struct hvc_struct *hp); +void hvc_kick(void); + +/* default notifier for irq based notification */ +extern int notifier_add_irq(struct hvc_struct *hp, int data); +extern void notifier_del_irq(struct hvc_struct *hp, int data); + #if defined(CONFIG_XMON) && defined(CONFIG_SMP) #include <asm/xmon.h> diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c new file mode 100644 index 00000000000..73a59cdb894 --- /dev/null +++ b/drivers/char/hvc_irq.c @@ -0,0 +1,44 @@ +/* + * Copyright IBM Corp. 2001,2008 + * + * This file contains the IRQ specific code for hvc_console + * + */ + +#include <linux/interrupt.h> + +#include "hvc_console.h" + +static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) +{ + /* if hvc_poll request a repoll, then kick the hvcd thread */ + if (hvc_poll(dev_instance)) + hvc_kick(); + return IRQ_HANDLED; +} + +/* + * For IRQ based systems these callbacks can be used + */ +int notifier_add_irq(struct hvc_struct *hp, int irq) +{ + int rc; + + if (!irq) { + hp->irq_requested = 0; + return 0; + } + rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, + "hvc_console", hp); + if (!rc) + hp->irq_requested = 1; + return rc; +} + +void notifier_del_irq(struct hvc_struct *hp, int irq) +{ + if (!irq) + return; + free_irq(irq, hp); + hp->irq_requested = 0; +} diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index a08f8f981c1..b71c610fe5a 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -200,6 +200,8 @@ done: static struct hv_ops hvc_get_put_ops = { .get_chars = get_chars, .put_chars = put_chars, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 79711aa4b41..93f3840c168 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) static struct hv_ops hvc_get_put_ops = { .get_chars = filtered_get_chars, .put_chars = hvc_put_chars, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index db2ae421627..6b70aa66a58 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c @@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len) static struct hv_ops hvc_ops = { .get_chars = read_console, .put_chars = write_console, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __init xen_init(void) diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 786d518e947..473d9b14439 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -114,7 +114,7 @@ * the hvcs_final_close() function in order to get it out of the spinlock. * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from - * include/asm-powerpc/hvcserver.h + * arch/powerepc/include/asm/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to * prevent possible lockup with realtime scheduling as similarily pointed out by diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 27fdc086649..8a2fce0756e 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -241,7 +241,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw) struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; u8 mfc, dvc; - /* interrupts disabled in stop_machine_run call */ + /* interrupts disabled in stop_machine call */ if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) pci_write_config_byte(intel_rng_hw->dev, @@ -365,10 +365,10 @@ static int __init mod_init(void) * location with the Read ID command, all activity on the system * must be stopped until the state is back to normal. * - * Use stop_machine_run because IPIs can be blocked by disabling + * Use stop_machine because IPIs can be blocked by disabling * interrupts. */ - err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS); + err = stop_machine(intel_rng_hw_init, intel_rng_hw, NULL); pci_dev_put(dev); iounmap(intel_rng_hw->mem); kfree(intel_rng_hw); diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index bab43ca32ac..263567f5f39 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -23,7 +23,7 @@ #include <linux/hw_random.h> #include <asm/io.h> -#include <asm/hardware.h> +#include <mach/hardware.h> static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 9cb48fcd316..689f9dcd3b8 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -203,7 +203,7 @@ static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); -static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); +static long ip2_ipl_ioctl(struct file *, UINT, ULONG); static int ip2_ipl_open(struct inode *, struct file *); static int DumpTraceBuffer(char __user *, int); @@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = { .owner = THIS_MODULE, .read = ip2_ipl_read, .write = ip2_ipl_write, - .ioctl = ip2_ipl_ioctl, + .unlocked_ioctl = ip2_ipl_ioctl, .open = ip2_ipl_open, }; @@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t /* */ /* */ /******************************************************************************/ -static int -ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) +static long +ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) { - unsigned int iplminor = iminor(pInode); + unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); int rc = 0; void __user *argp = (void __user *)arg; ULONG __user *pIndex = argp; @@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); #endif + lock_kernel(); + switch ( iplminor ) { case 0: // IPL device rc = -EINVAL; @@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) rc = -ENODEV; break; } + unlock_kernel(); return rc; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 192688344ed..f52931e1c16 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -66,8 +66,8 @@ #include <linux/ctype.h> #ifdef CONFIG_PPC_OF -#include <asm/of_device.h> -#include <asm/of_platform.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> #endif #define PFX "ipmi_si: " diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 50243fcd87e..4f8d67fed29 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c @@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0); static int mwave_open(struct inode *inode, struct file *file); static int mwave_close(struct inode *inode, struct file *file); -static int mwave_ioctl(struct inode *inode, struct file *filp, - unsigned int iocmd, unsigned long ioarg); +static long mwave_ioctl(struct file *filp, unsigned int iocmd, + unsigned long ioarg); MWAVE_DEVICE_DATA mwave_s_mdd; @@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file) return retval; } -static int mwave_ioctl(struct inode *inode, struct file *file, - unsigned int iocmd, unsigned long ioarg) +static long mwave_ioctl(struct file *file, unsigned int iocmd, + unsigned long ioarg) { unsigned int retval = 0; pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; void __user *arg = (void __user *)ioarg; - PRINTK_5(TRACE_MWAVE, - "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n", - inode, file, iocmd, (int) ioarg); + PRINTK_4(TRACE_MWAVE, + "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n", + file, iocmd, (int) ioarg); switch (iocmd) { @@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RESET" " calling tp3780I_ResetDSP\n"); + lock_kernel(); retval = tp3780I_ResetDSP(&pDrvData->rBDData); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RESET" " retval %x from tp3780I_ResetDSP\n", @@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RUN" " calling tp3780I_StartDSP\n"); + lock_kernel(); retval = tp3780I_StartDSP(&pDrvData->rBDData); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RUN" " retval %x from tp3780I_StartDSP\n", @@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, "mwavedd::mwave_ioctl," " IOCTL_MW_DSP_ABILITIES calling" " tp3780I_QueryAbilities\n"); + lock_kernel(); retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" " retval %x from tp3780I_QueryAbilities\n", @@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file, "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress); + unlock_kernel(); } break; @@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength / 2, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rReadData.ulDataLength / 2, rReadData.usDspAddress); + unlock_kernel(); } break; @@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + unlock_kernel(); } break; @@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd, pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + unlock_kernel(); } break; @@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, ipcnum); return -EINVAL; } + lock_kernel(); pDrvData->IPCs[ipcnum].bIsHere = FALSE; pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" @@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, return -EINVAL; } + lock_kernel(); if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { DECLARE_WAITQUEUE(wait, current); @@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " processing\n", ipcnum); } + unlock_kernel(); } break; @@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file, ipcnum); return -EINVAL; } + lock_kernel(); if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); } } + unlock_kernel(); } break; default: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" - " Error: Unrecognized iocmd %x\n", - iocmd); return -ENOTTY; break; } /* switch */ @@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = { .owner = THIS_MODULE, .read = mwave_read, .write = mwave_write, - .ioctl = mwave_ioctl, + .unlocked_ioctl = mwave_ioctl, .open = mwave_open, .release = mwave_close }; diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h index 8eca61e0a19..7e0d530e2e0 100644 --- a/drivers/char/mwave/mwavedd.h +++ b/drivers/char/mwave/mwavedd.h @@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA { } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; +extern MWAVE_DEVICE_DATA mwave_s_mdd; + #endif diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index f282976daaa..c6896970806 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -57,8 +57,6 @@ #include "3780i.h" #include "mwavepub.h" -extern MWAVE_DEVICE_DATA mwave_s_mdd; - static unsigned short s_ausThinkpadIrqToField[16] = { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 4c756bbba94..b638403e8e9 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -16,7 +16,6 @@ * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. * - Fixed x86_64 cleanness - * - Fixed sleep with spinlock held in mxser_send_break */ #include <linux/module.h> @@ -49,18 +48,12 @@ #define MXSER_VERSION "2.0.4" /* 1.12 */ #define MXSERMAJOR 174 -#define MXSERCUMAJOR 175 #define MXSER_BOARDS 4 /* Max. boards */ #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) #define MXSER_ISR_PASS_LIMIT 100 -#define MXSER_ERR_IOADDR -1 -#define MXSER_ERR_IRQ -2 -#define MXSER_ERR_IRQ_CONFLIT -3 -#define MXSER_ERR_VECTOR -4 - /*CheckIsMoxaMust return value*/ #define MOXA_OTHER_UART 0x00 #define MOXA_MUST_MU150_HWID 0x01 @@ -179,14 +172,15 @@ static struct pci_device_id mxser_pcibrds[] = { }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; +static unsigned long ioaddr[MXSER_BOARDS]; static int ttymajor = MXSERMAJOR; /* Variables for insmod */ MODULE_AUTHOR("Casper Yang"); MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); -module_param_array(ioaddr, int, NULL, 0); +module_param_array(ioaddr, ulong, NULL, 0); +MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); module_param(ttymajor, int, 0); MODULE_LICENSE("GPL"); @@ -196,7 +190,6 @@ struct mxser_log { unsigned long txcnt[MXSER_PORTS]; }; - struct mxser_mon { unsigned long rxcnt; unsigned long txcnt; @@ -287,19 +280,9 @@ struct mxser_mstatus { int dcd; }; -static struct mxser_mstatus GMStatus[MXSER_PORTS]; - -static int mxserBoardCAP[MXSER_BOARDS] = { - 0, 0, 0, 0 - /* 0x180, 0x280, 0x200, 0x320 */ -}; - static struct mxser_board mxser_boards[MXSER_BOARDS]; static struct tty_driver *mxvar_sdriver; static struct mxser_log mxvar_log; -static int mxvar_diagflag; -static unsigned char mxser_msr[MXSER_PORTS + 1]; -static struct mxser_mon_ext mon_data_ext; static int mxser_set_baud_method[MXSER_PORTS + 1]; static void mxser_enable_must_enchance_mode(unsigned long baseio) @@ -543,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info) static unsigned char mxser_get_msr(int baseaddr, int mode, int port) { + static unsigned char mxser_msr[MXSER_PORTS + 1]; unsigned char status = 0; status = inb(baseaddr + UART_MSR); @@ -1319,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty) struct mxser_port *info = tty->driver_data; unsigned long flags; - if (info->xmit_cnt <= 0 || - tty->stopped || - !info->port.xmit_buf || - (tty->hw_stopped && - (info->type != PORT_16550A) && - (!info->board->chip_flag) - )) + if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || + (tty->hw_stopped && info->type != PORT_16550A && + !info->board->chip_flag)) return; spin_lock_irqsave(&info->slock, flags); @@ -1343,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty) int ret; ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; + return ret < 0 ? 0 : ret; } static int mxser_chars_in_buffer(struct tty_struct *tty) @@ -1634,6 +1612,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) switch (cmd) { case MOXA_GET_MAJOR: + if (printk_ratelimit()) + printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " + "%x (GET_MAJOR), fix your userspace\n", + current->comm, cmd); return put_user(ttymajor, (int __user *)argp); case MOXA_CHKPORTENABLE: @@ -1651,62 +1633,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) ret = -EFAULT; unlock_kernel(); return ret; - case MOXA_GETMSTATUS: + case MOXA_GETMSTATUS: { + struct mxser_mstatus ms, __user *msu = argp; lock_kernel(); for (i = 0; i < MXSER_BOARDS; i++) for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { port = &mxser_boards[i].ports[j]; + memset(&ms, 0, sizeof(ms)); - GMStatus[i].ri = 0; - if (!port->ioaddr) { - GMStatus[i].dcd = 0; - GMStatus[i].dsr = 0; - GMStatus[i].cts = 0; - continue; - } + if (!port->ioaddr) + goto copy; if (!port->port.tty || !port->port.tty->termios) - GMStatus[i].cflag = - port->normal_termios.c_cflag; + ms.cflag = port->normal_termios.c_cflag; else - GMStatus[i].cflag = - port->port.tty->termios->c_cflag; + ms.cflag = port->port.tty->termios->c_cflag; status = inb(port->ioaddr + UART_MSR); - if (status & 0x80 /*UART_MSR_DCD */ ) - GMStatus[i].dcd = 1; - else - GMStatus[i].dcd = 0; - - if (status & 0x20 /*UART_MSR_DSR */ ) - GMStatus[i].dsr = 1; - else - GMStatus[i].dsr = 0; - - - if (status & 0x10 /*UART_MSR_CTS */ ) - GMStatus[i].cts = 1; - else - GMStatus[i].cts = 0; + if (status & UART_MSR_DCD) + ms.dcd = 1; + if (status & UART_MSR_DSR) + ms.dsr = 1; + if (status & UART_MSR_CTS) + ms.cts = 1; + copy: + if (copy_to_user(msu, &ms, sizeof(ms))) { + unlock_kernel(); + return -EFAULT; + } + msu++; } unlock_kernel(); - if (copy_to_user(argp, GMStatus, - sizeof(struct mxser_mstatus) * MXSER_PORTS)) - return -EFAULT; return 0; + } case MOXA_ASPP_MON_EXT: { - int p, shiftbit; - unsigned long opmode; - unsigned cflag, iflag; + struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ + unsigned int cflag, iflag, p; + u8 opmode; + + me = kzalloc(sizeof(*me), GFP_KERNEL); + if (!me) + return -ENOMEM; lock_kernel(); - for (i = 0; i < MXSER_BOARDS; i++) { - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + for (i = 0, p = 0; i < MXSER_BOARDS; i++) { + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { + if (p >= ARRAY_SIZE(me->rx_cnt)) { + i = MXSER_BOARDS; + break; + } port = &mxser_boards[i].ports[j]; if (!port->ioaddr) continue; - status = mxser_get_msr(port->ioaddr, 0, i); + status = mxser_get_msr(port->ioaddr, 0, p); if (status & UART_MSR_TERI) port->icount.rng++; @@ -1718,16 +1698,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) port->icount.cts++; port->mon_data.modem_status = status; - mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; - mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; - mon_data_ext.up_rxcnt[i] = - port->mon_data.up_rxcnt; - mon_data_ext.up_txcnt[i] = - port->mon_data.up_txcnt; - mon_data_ext.modem_status[i] = + me->rx_cnt[p] = port->mon_data.rxcnt; + me->tx_cnt[p] = port->mon_data.txcnt; + me->up_rxcnt[p] = port->mon_data.up_rxcnt; + me->up_txcnt[p] = port->mon_data.up_txcnt; + me->modem_status[p] = port->mon_data.modem_status; - mon_data_ext.baudrate[i] = - tty_get_baud_rate(port->port.tty); + me->baudrate[p] = tty_get_baud_rate(port->port.tty); if (!port->port.tty || !port->port.tty->termios) { cflag = port->normal_termios.c_cflag; @@ -1737,40 +1714,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) iflag = port->port.tty->termios->c_iflag; } - mon_data_ext.databits[i] = cflag & CSIZE; - - mon_data_ext.stopbits[i] = cflag & CSTOPB; - - mon_data_ext.parity[i] = - cflag & (PARENB | PARODD | CMSPAR); - - mon_data_ext.flowctrl[i] = 0x00; + me->databits[p] = cflag & CSIZE; + me->stopbits[p] = cflag & CSTOPB; + me->parity[p] = cflag & (PARENB | PARODD | + CMSPAR); if (cflag & CRTSCTS) - mon_data_ext.flowctrl[i] |= 0x03; + me->flowctrl[p] |= 0x03; if (iflag & (IXON | IXOFF)) - mon_data_ext.flowctrl[i] |= 0x0C; + me->flowctrl[p] |= 0x0C; if (port->type == PORT_16550A) - mon_data_ext.fifo[i] = 1; - else - mon_data_ext.fifo[i] = 0; + me->fifo[p] = 1; - p = i % 4; - shiftbit = p * 2; - opmode = inb(port->opmode_ioaddr) >> shiftbit; + opmode = inb(port->opmode_ioaddr) >> + ((p % 4) * 2); opmode &= OP_MODE_MASK; - - mon_data_ext.iftype[i] = opmode; - + me->iftype[p] = opmode; } } unlock_kernel(); - if (copy_to_user(argp, &mon_data_ext, - sizeof(mon_data_ext))) - return -EFAULT; - return 0; + if (copy_to_user(argp, me, sizeof(*me))) + ret = -EFAULT; + kfree(me); + return ret; } default: return -ENOIOCTLCMD; @@ -1804,7 +1772,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, { struct mxser_port *info = tty->driver_data; struct async_icount cnow; - struct serial_icounter_struct __user *p_cuser; unsigned long flags; void __user *argp = (void __user *)arg; int retval; @@ -1884,30 +1851,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, * NB: both 1->0 and 0->1 transitions are counted except for * RI where only 0->1 is counted. */ - case TIOCGICOUNT: + case TIOCGICOUNT: { + struct serial_icounter_struct icnt = { 0 }; spin_lock_irqsave(&info->slock, flags); cnow = info->icount; spin_unlock_irqrestore(&info->slock, flags); - p_cuser = argp; - if (put_user(cnow.frame, &p_cuser->frame)) - return -EFAULT; - if (put_user(cnow.brk, &p_cuser->brk)) - return -EFAULT; - if (put_user(cnow.overrun, &p_cuser->overrun)) - return -EFAULT; - if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) - return -EFAULT; - if (put_user(cnow.parity, &p_cuser->parity)) - return -EFAULT; - if (put_user(cnow.rx, &p_cuser->rx)) - return -EFAULT; - if (put_user(cnow.tx, &p_cuser->tx)) - return -EFAULT; - put_user(cnow.cts, &p_cuser->cts); - put_user(cnow.dsr, &p_cuser->dsr); - put_user(cnow.rng, &p_cuser->rng); - put_user(cnow.dcd, &p_cuser->dcd); - return 0; + + icnt.frame = cnow.frame; + icnt.brk = cnow.brk; + icnt.overrun = cnow.overrun; + icnt.buf_overrun = cnow.buf_overrun; + icnt.parity = cnow.parity; + icnt.rx = cnow.rx; + icnt.tx = cnow.tx; + icnt.cts = cnow.cts; + icnt.dsr = cnow.dsr; + icnt.rng = cnow.rng; + icnt.dcd = cnow.dcd; + + return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; + } case MOXA_HighSpeedOn: return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); case MOXA_SDS_RSTICOUNTER: @@ -2503,7 +2466,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, unsigned int i; int retval; - printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); + printk(KERN_INFO "mxser: max. baud rate = %d bps\n", + brd->ports[0].max_baud); for (i = 0; i < brd->info->nports; i++) { info = &brd->ports[i]; @@ -2586,28 +2550,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) irq = regs[9] & 0xF000; irq = irq | (irq >> 4); if (irq != (regs[9] & 0xFF00)) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } else if (brd->info->nports == 4) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if (irq != regs[9]) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } else if (brd->info->nports == 8) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if ((irq != regs[9]) || (irq != regs[10])) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } - if (!irq) - return MXSER_ERR_IRQ; + if (!irq) { + printk(KERN_ERR "mxser: interrupt number unset\n"); + return -EIO; + } brd->irq = ((int)(irq & 0xF000) >> 12); for (i = 0; i < 8; i++) brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; - if ((regs[12] & 0x80) == 0) - return MXSER_ERR_VECTOR; + if ((regs[12] & 0x80) == 0) { + printk(KERN_ERR "mxser: invalid interrupt vector\n"); + return -EIO; + } brd->vector = (int)regs[11]; /* interrupt vector */ if (id == 1) brd->vector_mask = 0x00FF; @@ -2634,13 +2602,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) else brd->uart_type = PORT_16450; if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, - "mxser(IO)")) - return MXSER_ERR_IOADDR; + "mxser(IO)")) { + printk(KERN_ERR "mxser: can't request ports I/O region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; + } if (!request_region(brd->vector, 1, "mxser(vector)")) { release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - return MXSER_ERR_VECTOR; + printk(KERN_ERR "mxser: can't request interrupt vector region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; } return brd->info->nports; + +err_irqconflict: + printk(KERN_ERR "mxser: invalid interrupt number\n"); + return -EIO; } static int __devinit mxser_probe(struct pci_dev *pdev, @@ -2657,20 +2638,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev, break; if (i >= MXSER_BOARDS) { - printk(KERN_ERR "Too many Smartio/Industio family boards found " - "(maximum %d), board not configured\n", MXSER_BOARDS); + dev_err(&pdev->dev, "too many boards found (maximum %d), board " + "not configured\n", MXSER_BOARDS); goto err; } brd = &mxser_boards[i]; brd->idx = i * MXSER_PORTS_PER_BOARD; - printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", + dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", mxser_cards[ent->driver_data].name, pdev->bus->number, PCI_SLOT(pdev->devfn)); retval = pci_enable_device(pdev); if (retval) { - printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + dev_err(&pdev->dev, "PCI enable failed\n"); goto err; } @@ -2772,11 +2753,8 @@ static struct pci_driver mxser_driver = { static int __init mxser_module_init(void) { struct mxser_board *brd; - unsigned long cap; - unsigned int i, m, isaloop; - int retval, b; - - pr_debug("Loading module mxser ...\n"); + unsigned int b, i, m; + int retval; mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); if (!mxvar_sdriver) @@ -2806,74 +2784,43 @@ static int __init mxser_module_init(void) goto err_put; } - mxvar_diagflag = 0; - - m = 0; /* Start finding ISA boards here */ - for (isaloop = 0; isaloop < 2; isaloop++) - for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { - if (!isaloop) - cap = mxserBoardCAP[b]; /* predefined */ - else - cap = ioaddr[b]; /* module param */ - - if (!cap) - continue; + for (m = 0, b = 0; b < MXSER_BOARDS; b++) { + if (!ioaddr[b]) + continue; + + brd = &mxser_boards[m]; + retval = mxser_get_ISA_conf(!ioaddr[b], brd); + if (retval <= 0) { + brd->info = NULL; + continue; + } - brd = &mxser_boards[m]; - retval = mxser_get_ISA_conf(cap, brd); - - if (retval != 0) - printk(KERN_INFO "Found MOXA %s board " - "(CAP=0x%x)\n", - brd->info->name, ioaddr[b]); - - if (retval <= 0) { - if (retval == MXSER_ERR_IRQ) - printk(KERN_ERR "Invalid interrupt " - "number, board not " - "configured\n"); - else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk(KERN_ERR "Invalid interrupt " - "number, board not " - "configured\n"); - else if (retval == MXSER_ERR_VECTOR) - printk(KERN_ERR "Invalid interrupt " - "vector, board not " - "configured\n"); - else if (retval == MXSER_ERR_IOADDR) - printk(KERN_ERR "Invalid I/O address, " - "board not configured\n"); - - brd->info = NULL; - continue; - } + printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", + brd->info->name, ioaddr[b]); - /* mxser_initbrd will hook ISR. */ - if (mxser_initbrd(brd, NULL) < 0) { - brd->info = NULL; - continue; - } + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, NULL) < 0) { + brd->info = NULL; + continue; + } - brd->idx = m * MXSER_PORTS_PER_BOARD; - for (i = 0; i < brd->info->nports; i++) - tty_register_device(mxvar_sdriver, brd->idx + i, - NULL); + brd->idx = m * MXSER_PORTS_PER_BOARD; + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, NULL); - m++; - } + m++; + } retval = pci_register_driver(&mxser_driver); if (retval) { - printk(KERN_ERR "Can't register pci driver\n"); + printk(KERN_ERR "mxser: can't register pci driver\n"); if (!m) { retval = -ENODEV; goto err_unr; } /* else: we have some ISA cards under control */ } - pr_debug("Done.\n"); - return 0; err_unr: tty_unregister_driver(mxvar_sdriver); @@ -2886,8 +2833,6 @@ static void __exit mxser_module_exit(void) { unsigned int i, j; - pr_debug("Unloading module mxser ...\n"); - pci_unregister_driver(&mxser_driver); for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ @@ -2901,8 +2846,6 @@ static void __exit mxser_module_exit(void) for (i = 0; i < MXSER_BOARDS; i++) if (mxser_boards[i].info != NULL) mxser_release_res(&mxser_boards[i], NULL, 1); - - pr_debug("Done.\n"); } module_init(mxser_module_init); diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index ba012c2bdf7..006be92ee3f 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -122,35 +122,20 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm static ssize_t flash_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { - unsigned long p = *ppos; - unsigned int count = size; - int ret = 0; + ssize_t ret; if (flashdebug) - printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " - "buffer=%p, count=0x%X.\n", p, buf, count); - - if (count) - ret = -ENXIO; + printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, " + "buffer=%p, count=0x%zx.\n", *ppos, buf, size); + /* + * We now lock against reads and writes. --rmk + */ + if (mutex_lock_interruptible(&nwflash_mutex)) + return -ERESTARTSYS; - if (p < gbFlashSize) { - if (count > gbFlashSize - p) - count = gbFlashSize - p; + ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize); + mutex_unlock(&nwflash_mutex); - /* - * We now lock against reads and writes. --rmk - */ - if (mutex_lock_interruptible(&nwflash_mutex)) - return -ERESTARTSYS; - - ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); - if (ret == 0) { - ret = count; - *ppos += count; - } else - ret = -EFAULT; - mutex_unlock(&nwflash_mutex); - } return ret; } diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 929101ecbae..4c1820cad71 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -30,11 +30,11 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw); static void handle_received_SETUP_packet(struct ipw_hardware *ipw, unsigned int address, - unsigned char *data, int len, + const unsigned char *data, int len, int is_last); static void ipwireless_setup_timer(unsigned long data); static void handle_received_CTRL_packet(struct ipw_hardware *hw, - unsigned int channel_idx, unsigned char *data, int len); + unsigned int channel_idx, const unsigned char *data, int len); /*#define TIMING_DIAGNOSTICS*/ @@ -79,8 +79,7 @@ static void report_timing(void) timing_stats.last_report_time = jiffies; if (!first) printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": %u us elapsed - read %lu bytes in %u us, " - "wrote %lu bytes in %u us\n", + ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", jiffies_to_usecs(since), timing_stats.read_bytes, jiffies_to_usecs(timing_stats.read_time), @@ -133,29 +132,17 @@ enum { #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 struct nl_first_packet_header { -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char packet_rank:2; - unsigned char address:3; - unsigned char protocol:3; -#else unsigned char protocol:3; unsigned char address:3; unsigned char packet_rank:2; -#endif unsigned char length_lsb; unsigned char length_msb; }; struct nl_packet_header { -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char packet_rank:2; - unsigned char address:3; - unsigned char protocol:3; -#else unsigned char protocol:3; unsigned char address:3; unsigned char packet_rank:2; -#endif }; /* Value of 'packet_rank' above */ @@ -227,15 +214,12 @@ struct MEMINFREG { unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ }; -#define IODMADPR 0x00 /* DMA Data Port Register (R/W) */ - #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) #define MEMTX_TX 0x0001 #define MEMRX_RX 0x0001 #define MEMRX_RX_DONE 0x0001 #define MEMRX_PCINTACKK 0x0001 -#define MEMRX_MEMSPURIOUSINT 0x0001 #define NL_NUM_OF_PRIORITIES 3 #define NL_NUM_OF_PROTOCOLS 3 @@ -245,7 +229,7 @@ struct ipw_hardware { unsigned int base_port; short hw_version; unsigned short ll_mtu; - spinlock_t spinlock; + spinlock_t lock; int initializing; int init_loops; @@ -386,26 +370,52 @@ static void dump_data_bytes(const char *type, const unsigned char *data, length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); } -static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, +static void swap_packet_bitfield_to_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from aa.bbb.ccc to ccc.bbb.aa + */ + ret |= tmp & 0xc0 >> 6; + ret |= tmp & 0x38 >> 1; + ret |= tmp & 0x07 << 5; + *data = ret & 0xff; +#endif +} + +static void swap_packet_bitfield_from_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from ccc.bbb.aa to aa.bbb.ccc + */ + ret |= tmp & 0xe0 >> 5; + ret |= tmp & 0x1c << 1; + ret |= tmp & 0x03 << 6; + *data = ret & 0xff; +#endif +} + +static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, unsigned length) { - int i; + unsigned i; unsigned long flags; start_timing(); - - if (length == 0) - return 0; - - if (length > hw->ll_mtu) - return -1; + BUG_ON(length > hw->ll_mtu); if (ipwireless_debug) dump_data_bytes("send", data, length); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 0; + swap_packet_bitfield_to_le(data); if (hw->hw_version == HW_VERSION_1) { outw((unsigned short) length, hw->base_port + IODWR); @@ -414,7 +424,7 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, unsigned short d = data[i]; __le16 raw_data; - if (likely(i + 1 < length)) + if (i + 1 < length) d |= data[i + 1] << 8; raw_data = cpu_to_le16(d); outw(raw_data, hw->base_port + IODWR); @@ -422,32 +432,30 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, outw(DCR_TXDONE, hw->base_port + IODCR); } else if (hw->hw_version == HW_VERSION_2) { - outw((unsigned short) length, hw->base_port + IODMADPR); + outw((unsigned short) length, hw->base_port); for (i = 0; i < length; i += 2) { unsigned short d = data[i]; __le16 raw_data; - if ((i + 1 < length)) + if (i + 1 < length) d |= data[i + 1] << 8; raw_data = cpu_to_le16(d); - outw(raw_data, hw->base_port + IODMADPR); + outw(raw_data, hw->base_port); } while ((i & 3) != 2) { - outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR); + outw((unsigned short) 0xDEAD, hw->base_port); i += 2; } writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); end_write_timing(length); - - return 0; } -static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) +static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) { unsigned short fragment_data_len; unsigned short data_left = packet->length - packet->offset; @@ -462,6 +470,10 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) if (data_left < fragment_data_len) fragment_data_len = data_left; + /* + * hdr_first is now in machine bitfield order, which will be swapped + * to le just before it goes to hw + */ pkt.hdr_first.protocol = packet->protocol; pkt.hdr_first.address = packet->dest_addr; pkt.hdr_first.packet_rank = 0; @@ -493,25 +505,23 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) */ unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add(&packet->queue, &hw->tx_queue[0]); hw->tx_queued++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } else { if (packet->packet_callback) packet->packet_callback(packet->callback_data, packet->length); kfree(packet); } - - return 0; } static void ipw_setup_hardware(struct ipw_hardware *hw) { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->hw_version == HW_VERSION_1) { /* Reset RX FIFO */ outw(DCR_RXRESET, hw->base_port + IODCR); @@ -530,7 +540,7 @@ static void ipw_setup_hardware(struct ipw_hardware *hw) csr |= 1; writew(csr, &hw->memregs_CCR->reg_config_and_status); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } /* @@ -549,28 +559,23 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, if (!packet) { unsigned long flags; - /* - * If this is the first fragment, then we will need to fetch a - * packet to put it in. - */ - spin_lock_irqsave(&hw->spinlock, flags); - /* If we have one in our pool, then pull it out. */ + spin_lock_irqsave(&hw->lock, flags); if (!list_empty(&hw->rx_pool)) { packet = list_first_entry(&hw->rx_pool, struct ipw_rx_packet, queue); - list_del(&packet->queue); hw->rx_pool_size--; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); + list_del(&packet->queue); } else { - /* Otherwise allocate a new one. */ - static int min_capacity = 256; + const int min_capacity = + ipwireless_ppp_mru(hw->network) + 2; int new_capacity; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); new_capacity = - minimum_free_space > min_capacity - ? minimum_free_space - : min_capacity; + (minimum_free_space > min_capacity + ? minimum_free_space + : min_capacity); packet = kmalloc(sizeof(struct ipw_rx_packet) + new_capacity, GFP_ATOMIC); if (!packet) @@ -580,10 +585,6 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, packet->length = 0; } - /* - * If this packet does not have sufficient capacity for the data we - * want to add, then make it bigger. - */ if (packet->length + minimum_free_space > packet->capacity) { struct ipw_rx_packet *old_packet = packet; @@ -610,13 +611,15 @@ static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) kfree(packet); else { hw->rx_pool_size++; - list_add_tail(&packet->queue, &hw->rx_pool); + list_add(&packet->queue, &hw->rx_pool); } } static void queue_received_packet(struct ipw_hardware *hw, - unsigned int protocol, unsigned int address, - unsigned char *data, int length, int is_last) + unsigned int protocol, + unsigned int address, + const unsigned char *data, int length, + int is_last) { unsigned int channel_idx = address - 1; struct ipw_rx_packet *packet = NULL; @@ -658,9 +661,9 @@ static void queue_received_packet(struct ipw_hardware *hw, packet = *assem; *assem = NULL; /* Count queued DATA bytes only */ - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_bytes_queued += packet->length; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } } else { /* If it's a CTRL packet, don't assemble, just queue it. */ @@ -682,13 +685,13 @@ static void queue_received_packet(struct ipw_hardware *hw, * network layer. */ if (packet) { - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add_tail(&packet->queue, &hw->rx_queue); /* Block reception of incoming packets if queue is full. */ hw->blocking_rx = - hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; + (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); schedule_work(&hw->work_rx); } } @@ -702,7 +705,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) container_of(work_rx, struct ipw_hardware, work_rx); unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); while (!list_empty(&hw->rx_queue)) { struct ipw_rx_packet *packet = list_first_entry(&hw->rx_queue, @@ -720,7 +723,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) if (packet->protocol == TL_PROTOCOLID_COM_DATA) { if (hw->network != NULL) { /* If the network hasn't been disconnected. */ - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); /* * This must run unlocked due to tty processing * and mutex locking @@ -731,7 +734,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) (unsigned char *)packet + sizeof(struct ipw_rx_packet), packet->length); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); } /* Count queued DATA bytes only */ hw->rx_bytes_queued -= packet->length; @@ -755,15 +758,15 @@ static void ipw_receive_data_work(struct work_struct *work_rx) if (hw->shutting_down) break; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } static void handle_received_CTRL_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, int len) + const unsigned char *data, int len) { - struct ipw_control_packet_body *body = - (struct ipw_control_packet_body *) data; + const struct ipw_control_packet_body *body = + (const struct ipw_control_packet_body *) data; unsigned int changed_mask; if (len != sizeof(struct ipw_control_packet_body)) { @@ -805,13 +808,13 @@ static void handle_received_CTRL_packet(struct ipw_hardware *hw, } static void handle_received_packet(struct ipw_hardware *hw, - union nl_packet *packet, + const union nl_packet *packet, unsigned short len) { unsigned int protocol = packet->hdr.protocol; unsigned int address = packet->hdr.address; unsigned int header_length; - unsigned char *data; + const unsigned char *data; unsigned int data_len; int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; @@ -850,7 +853,7 @@ static void acknowledge_data_read(struct ipw_hardware *hw) static void do_receive_packet(struct ipw_hardware *hw) { unsigned len; - unsigned int i; + unsigned i; unsigned char pkt[LL_MTU_MAX]; start_timing(); @@ -859,8 +862,7 @@ static void do_receive_packet(struct ipw_hardware *hw) len = inw(hw->base_port + IODRR); if (len > hw->ll_mtu) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - " - "longer than the MTU!\n", len); + ": received a packet of %u bytes - longer than the MTU!\n", len); outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); return; } @@ -873,18 +875,17 @@ static void do_receive_packet(struct ipw_hardware *hw) pkt[i + 1] = (unsigned char) (data >> 8); } } else { - len = inw(hw->base_port + IODMADPR); + len = inw(hw->base_port); if (len > hw->ll_mtu) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - " - "longer than the MTU!\n", len); + ": received a packet of %u bytes - longer than the MTU!\n", len); writew(MEMRX_PCINTACKK, &hw->memory_info_regs->memreg_pc_interrupt_ack); return; } for (i = 0; i < len; i += 2) { - __le16 raw_data = inw(hw->base_port + IODMADPR); + __le16 raw_data = inw(hw->base_port); unsigned short data = le16_to_cpu(raw_data); pkt[i] = (unsigned char) data; @@ -892,13 +893,15 @@ static void do_receive_packet(struct ipw_hardware *hw) } while ((i & 3) != 2) { - inw(hw->base_port + IODMADPR); + inw(hw->base_port); i += 2; } } acknowledge_data_read(hw); + swap_packet_bitfield_from_le(pkt); + if (ipwireless_debug) dump_data_bytes("recv", pkt, len); @@ -916,8 +919,7 @@ static int get_current_packet_priority(struct ipw_hardware *hw) * until setup is complete. */ return (hw->to_setup || hw->initializing - ? PRIO_SETUP + 1 : - NL_NUM_OF_PRIORITIES); + ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); } /* @@ -928,17 +930,17 @@ static int get_packets_from_hw(struct ipw_hardware *hw) int received = 0; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); while (hw->rx_ready && !hw->blocking_rx) { received = 1; hw->rx_ready--; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); do_receive_packet(hw); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return received; } @@ -954,7 +956,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) int more_to_send = 0; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->tx_queued && hw->tx_ready) { int priority; struct ipw_tx_packet *packet = NULL; @@ -975,17 +977,17 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) } if (!packet) { hw->tx_queued = 0; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return 0; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); /* Send */ do_send_packet(hw, packet); /* Check if more to send */ - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); for (priority = 0; priority < priority_limit; priority++) if (!list_empty(&hw->tx_queue[priority])) { more_to_send = 1; @@ -995,7 +997,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) if (!more_to_send) hw->tx_queued = 0; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return more_to_send; } @@ -1008,9 +1010,9 @@ static void ipwireless_do_tasklet(unsigned long hw_) struct ipw_hardware *hw = (struct ipw_hardware *) hw_; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->shutting_down) { - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return; } @@ -1019,7 +1021,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) * Initial setup data sent to hardware */ hw->to_setup = 2; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); ipw_setup_hardware(hw); ipw_send_setup_packet(hw); @@ -1030,7 +1032,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) int priority_limit = get_current_packet_priority(hw); int again; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); do { again = send_pending_packet(hw, priority_limit); @@ -1068,16 +1070,16 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, /* Transmit complete. */ if (irqn & IR_TXINTR) { ack |= IR_TXINTR; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } /* Received data */ if (irqn & IR_RXINTR) { ack |= IR_RXINTR; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } if (ack != 0) { outw(ack, hw->base_port + IOIR); @@ -1128,9 +1130,8 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, } else { return IRQ_NONE; } - } else { + } else return IRQ_NONE; - } } /* @@ -1149,9 +1150,9 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, if (hw->serial_number_detected) { if (memtx_serial != hw->last_memtx_serial) { hw->last_memtx_serial = memtx_serial; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); rx = 1; } else /* Ignore 'Timer Recovery' duplicates. */ @@ -1166,18 +1167,18 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": memreg_tx serial num detected\n"); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } rx = 1; } } if (memrxdone & MEMRX_RX_DONE) { writew(0, &hw->memory_info_regs->memreg_rx_done); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); tx = 1; } if (tx) @@ -1195,8 +1196,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, ": spurious interrupt - new_tx mode\n"); else { printk(KERN_WARNING IPWIRELESS_PCCARD_NAME - ": no valid memreg_tx value - " - "switching to the old memreg_tx\n"); + ": no valid memreg_tx value - switching to the old memreg_tx\n"); hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old; try_mem_tx_old = 1; @@ -1211,7 +1211,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, return IRQ_HANDLED; } -irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t ipwireless_interrupt(int irq, void *dev_id) { struct ipw_hardware *hw = dev_id; @@ -1226,9 +1226,9 @@ static void flush_packets_to_hw(struct ipw_hardware *hw) int priority_limit; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); priority_limit = get_current_packet_priority(hw); - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); while (send_pending_packet(hw, priority_limit)); } @@ -1238,10 +1238,10 @@ static void send_packet(struct ipw_hardware *hw, int priority, { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add_tail(&packet->queue, &hw->tx_queue[priority]); hw->tx_queued++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); flush_packets_to_hw(hw); } @@ -1291,21 +1291,20 @@ static void *alloc_ctrl_packet(int header_size, } int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, unsigned int length, + const unsigned char *data, unsigned int length, void (*callback) (void *cb, unsigned int length), void *callback_data) { struct ipw_tx_packet *packet; - packet = alloc_data_packet(length, - (unsigned char) (channel_idx + 1), - TL_PROTOCOLID_COM_DATA); + packet = alloc_data_packet(length, (channel_idx + 1), + TL_PROTOCOLID_COM_DATA); if (!packet) return -ENOMEM; packet->packet_callback = callback; packet->callback_data = callback_data; - memcpy((unsigned char *) packet + - sizeof(struct ipw_tx_packet), data, length); + memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, + length); send_packet(hw, PRIO_DATA, packet); return 0; @@ -1321,12 +1320,11 @@ static int set_control_line(struct ipw_hardware *hw, int prio, protocolid = TL_PROTOCOLID_SETUP; packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), - (unsigned char) (channel_idx + 1), - protocolid, line); + (channel_idx + 1), protocolid, line); if (!packet) return -ENOMEM; packet->header.length = sizeof(struct ipw_control_packet_body); - packet->body.value = (unsigned char) (state == 0 ? 0 : 1); + packet->body.value = (state == 0 ? 0 : 1); send_packet(hw, prio, &packet->header); return 0; } @@ -1504,8 +1502,7 @@ static void handle_setup_get_version_rsp(struct ipw_hardware *hw, if (vers_no == TL_SETUP_VERSION) __handle_setup_get_version_rsp(hw); else - printk(KERN_ERR - IPWIRELESS_PCCARD_NAME + printk(KERN_ERR IPWIRELESS_PCCARD_NAME ": invalid hardware version no %u\n", (unsigned int) vers_no); } @@ -1528,10 +1525,10 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw) static void handle_received_SETUP_packet(struct ipw_hardware *hw, unsigned int address, - unsigned char *data, int len, + const unsigned char *data, int len, int is_last) { - union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data; + const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; if (address != ADDR_SETUP_PROT) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME @@ -1629,7 +1626,7 @@ struct ipw_hardware *ipwireless_hardware_create(void) INIT_LIST_HEAD(&hw->rx_queue); INIT_LIST_HEAD(&hw->rx_pool); - spin_lock_init(&hw->spinlock); + spin_lock_init(&hw->lock); tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); INIT_WORK(&hw->work_rx, ipw_receive_data_work); setup_timer(&hw->setup_timer, ipwireless_setup_timer, @@ -1651,8 +1648,8 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw, enable_irq(hw->irq); } hw->base_port = base_port; - hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1; - hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2; + hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); + hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); hw->memregs_CCR = (struct MEMCCR __iomem *) ((unsigned short __iomem *) attr_memory + 0x200); hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; @@ -1695,10 +1692,10 @@ static void ipwireless_setup_timer(unsigned long data) if (is_card_present(hw)) { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->to_setup = 1; hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); tasklet_schedule(&hw->tasklet); } diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h index 19ce5eb266b..90a8590e43b 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.h +++ b/drivers/char/pcmcia/ipwireless/hardware.h @@ -34,14 +34,14 @@ struct ipw_network; struct ipw_hardware *ipwireless_hardware_create(void); void ipwireless_hardware_free(struct ipw_hardware *hw); -irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs); +irqreturn_t ipwireless_interrupt(int irq, void *dev_id); int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, int state); int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, int state); int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, + const unsigned char *data, unsigned int length, void (*packet_sent_callback) (void *cb, unsigned int length), diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index cc7dcea2d28..5eca7a99afe 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -49,7 +49,7 @@ static void ipwireless_detach(struct pcmcia_device *link); /* Debug mode: more verbose, print sent/recv bytes */ int ipwireless_debug; int ipwireless_loopback; -int ipwireless_out_queue = 1; +int ipwireless_out_queue = 10; module_param_named(debug, ipwireless_debug, int, 0); module_param_named(loopback, ipwireless_loopback, int, 0); @@ -57,7 +57,7 @@ module_param_named(out_queue, ipwireless_out_queue, int, 0); MODULE_PARM_DESC(debug, "switch on debug messages [0]"); MODULE_PARM_DESC(loopback, "debug: enable ras_raw channel [0]"); -MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]"); +MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); /* Executes in process context. */ static void signalled_reboot_work(struct work_struct *work_reboot) @@ -88,8 +88,6 @@ static int config_ipwireless(struct ipw_dev *ipw) unsigned short buf[64]; cisparse_t parse; unsigned short cor_value; - win_req_t request_attr_memory; - win_req_t request_common_memory; memreq_t memreq_attr_memory; memreq_t memreq_common_memory; @@ -188,6 +186,9 @@ static int config_ipwireless(struct ipw_dev *ipw) goto exit0; } + request_region(link->io.BasePort1, link->io.NumPorts1, + IPWIRELESS_PCCARD_NAME); + /* memory settings */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -214,16 +215,16 @@ static int config_ipwireless(struct ipw_dev *ipw) } if (parse.cftable_entry.mem.nwin > 0) { - request_common_memory.Attributes = + ipw->request_common_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; - request_common_memory.Base = + ipw->request_common_memory.Base = parse.cftable_entry.mem.win[0].host_addr; - request_common_memory.Size = parse.cftable_entry.mem.win[0].len; - if (request_common_memory.Size < 0x1000) - request_common_memory.Size = 0x1000; - request_common_memory.AccessSpeed = 0; + ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; + if (ipw->request_common_memory.Size < 0x1000) + ipw->request_common_memory.Size = 0x1000; + ipw->request_common_memory.AccessSpeed = 0; - ret = pcmcia_request_window(&link, &request_common_memory, + ret = pcmcia_request_window(&link, &ipw->request_common_memory, &ipw->handle_common_memory); if (ret != CS_SUCCESS) { @@ -246,16 +247,18 @@ static int config_ipwireless(struct ipw_dev *ipw) ipw->is_v2_card = parse.cftable_entry.mem.win[0].len == 0x100; - ipw->common_memory = ioremap(request_common_memory.Base, - request_common_memory.Size); + ipw->common_memory = ioremap(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); + request_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); - request_attr_memory.Attributes = + ipw->request_attr_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; - request_attr_memory.Base = 0; - request_attr_memory.Size = 0; /* this used to be 0x1000 */ - request_attr_memory.AccessSpeed = 0; + ipw->request_attr_memory.Base = 0; + ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ + ipw->request_attr_memory.AccessSpeed = 0; - ret = pcmcia_request_window(&link, &request_attr_memory, + ret = pcmcia_request_window(&link, &ipw->request_attr_memory, &ipw->handle_attr_memory); if (ret != CS_SUCCESS) { @@ -274,8 +277,10 @@ static int config_ipwireless(struct ipw_dev *ipw) goto exit2; } - ipw->attr_memory = ioremap(request_attr_memory.Base, - request_attr_memory.Size); + ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); + request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, + IPWIRELESS_PCCARD_NAME); } INIT_WORK(&ipw->work_reboot, signalled_reboot_work); @@ -311,14 +316,13 @@ static int config_ipwireless(struct ipw_dev *ipw) (unsigned int) link->irq.AssignedIRQ); if (ipw->attr_memory && ipw->common_memory) printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": attr memory 0x%08lx-0x%08lx, " - "common memory 0x%08lx-0x%08lx\n", - request_attr_memory.Base, - request_attr_memory.Base - + request_attr_memory.Size - 1, - request_common_memory.Base, - request_common_memory.Base - + request_common_memory.Size - 1); + ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", + ipw->request_attr_memory.Base, + ipw->request_attr_memory.Base + + ipw->request_attr_memory.Size - 1, + ipw->request_common_memory.Base, + ipw->request_common_memory.Base + + ipw->request_common_memory.Size - 1); ipw->network = ipwireless_network_create(ipw->hardware); if (!ipw->network) @@ -350,12 +354,16 @@ exit4: pcmcia_disable_device(link); exit3: if (ipw->attr_memory) { + release_mem_region(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); pcmcia_release_window(ipw->handle_attr_memory); pcmcia_disable_device(link); } exit2: if (ipw->common_memory) { + release_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); iounmap(ipw->common_memory); pcmcia_release_window(ipw->handle_common_memory); } @@ -367,19 +375,25 @@ exit0: static void release_ipwireless(struct ipw_dev *ipw) { - struct pcmcia_device *link = ipw->link; - - pcmcia_disable_device(link); + pcmcia_disable_device(ipw->link); - if (ipw->common_memory) + if (ipw->common_memory) { + release_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); iounmap(ipw->common_memory); - if (ipw->attr_memory) + } + if (ipw->attr_memory) { + release_mem_region(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); + } if (ipw->common_memory) pcmcia_release_window(ipw->handle_common_memory); if (ipw->attr_memory) pcmcia_release_window(ipw->handle_attr_memory); - pcmcia_disable_device(link); + + /* Break the link with Card Services */ + pcmcia_disable_device(ipw->link); } /* @@ -437,10 +451,6 @@ static void ipwireless_detach(struct pcmcia_device *link) release_ipwireless(ipw); - /* Break the link with Card Services */ - if (link) - pcmcia_disable_device(link); - if (ipw->tty != NULL) ipwireless_tty_free(ipw->tty); if (ipw->network != NULL) diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 1bfdcc8d47d..0e0363af9ab 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h @@ -45,10 +45,15 @@ struct ipw_tty; struct ipw_dev { struct pcmcia_device *link; int is_v2_card; + window_handle_t handle_attr_memory; void __iomem *attr_memory; + win_req_t request_attr_memory; + window_handle_t handle_common_memory; void __iomem *common_memory; + win_req_t request_common_memory; + dev_node_t nodes[2]; /* Reference to attribute memory, containing CIS data */ void *attribute_memory; diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index fe914d34f7f..590762a7f21 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c @@ -29,7 +29,6 @@ #include "main.h" #include "tty.h" -#define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue #define MAX_ASSOCIATED_TTYS 2 #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) @@ -46,7 +45,7 @@ struct ipw_network { /* Number of packets queued up in hardware module. */ int outgoing_packets_queued; /* Spinlock to avoid interrupts during shutdown */ - spinlock_t spinlock; + spinlock_t lock; struct mutex close_lock; /* PPP ioctl data, not actually used anywere */ @@ -68,20 +67,20 @@ static void notify_packet_sent(void *callback_data, unsigned int packet_length) struct ipw_network *network = callback_data; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); network->outgoing_packets_queued--; if (network->ppp_channel != NULL) { if (network->ppp_blocked) { network->ppp_blocked = 0; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); ppp_output_wakeup(network->ppp_channel); if (ipwireless_debug) - printk(KERN_INFO IPWIRELESS_PCCARD_NAME + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp unblocked\n"); } else - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } else - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } /* @@ -93,8 +92,8 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, struct ipw_network *network = ppp_channel->private; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); - if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) { + spin_lock_irqsave(&network->lock, flags); + if (network->outgoing_packets_queued < ipwireless_out_queue) { unsigned char *buf; static unsigned char header[] = { PPP_ALLSTATIONS, /* 0xff */ @@ -103,7 +102,7 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, int ret; network->outgoing_packets_queued++; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); /* * If we have the requested amount of headroom in the skb we @@ -144,7 +143,9 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, * needs to be unblocked once we are ready to send. */ network->ppp_blocked = 1; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); return 0; } } @@ -249,11 +250,11 @@ static void do_go_online(struct work_struct *work_go_online) work_go_online); unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (!network->ppp_channel) { struct ppp_channel *channel; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); if (!channel) { printk(KERN_ERR IPWIRELESS_PCCARD_NAME @@ -273,10 +274,10 @@ static void do_go_online(struct work_struct *work_go_online) network->xaccm[3] = 0x60000000U; network->raccm = ~0U; ppp_register_channel(channel); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); network->ppp_channel = channel; } - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } static void do_go_offline(struct work_struct *work_go_offline) @@ -287,16 +288,16 @@ static void do_go_offline(struct work_struct *work_go_offline) unsigned long flags; mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) { struct ppp_channel *channel = network->ppp_channel; network->ppp_channel = NULL; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); ppp_unregister_channel(channel); } else { - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); } } @@ -381,18 +382,18 @@ void ipwireless_network_packet_received(struct ipw_network *network, * the PPP layer. */ mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) { struct sk_buff *skb; - spin_unlock_irqrestore(&network->spinlock, + spin_unlock_irqrestore(&network->lock, flags); /* Send the data to the ppp_generic module. */ skb = ipw_packet_received_skb(data, length); ppp_input(network->ppp_channel, skb); } else - spin_unlock_irqrestore(&network->spinlock, + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); } @@ -410,7 +411,7 @@ struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) if (!network) return NULL; - spin_lock_init(&network->spinlock); + spin_lock_init(&network->lock); mutex_init(&network->close_lock); network->hardware = hw; @@ -478,10 +479,10 @@ int ipwireless_ppp_channel_index(struct ipw_network *network) int ret = -1; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) ret = ppp_channel_index(network->ppp_channel); - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); return ret; } @@ -491,10 +492,15 @@ int ipwireless_ppp_unit_number(struct ipw_network *network) int ret = -1; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) ret = ppp_unit_number(network->ppp_channel); - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); return ret; } + +int ipwireless_ppp_mru(const struct ipw_network *network) +{ + return network->mru; +} diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h index ccacd26fc7e..561f765b333 100644 --- a/drivers/char/pcmcia/ipwireless/network.h +++ b/drivers/char/pcmcia/ipwireless/network.h @@ -48,5 +48,6 @@ void ipwireless_ppp_open(struct ipw_network *net); void ipwireless_ppp_close(struct ipw_network *net); int ipwireless_ppp_channel_index(struct ipw_network *net); int ipwireless_ppp_unit_number(struct ipw_network *net); +int ipwireless_ppp_mru(const struct ipw_network *net); #endif diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 42f3815c5ce..b1414507997 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -259,7 +259,7 @@ static int ipw_write(struct tty_struct *linux_tty, } ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, - (unsigned char *) buf, count, + buf, count, ipw_write_packet_sent_callback, tty); if (ret == -1) { mutex_unlock(&tty->ipw_tty_mutex); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d1fceabe3ae..c240562c218 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -232,7 +232,6 @@ typedef struct _mgslpc_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -459,13 +458,11 @@ static int ttymajor=0; static int debug_level = 0; static int maxframe[MAX_DEVICE_COUNT] = {0,}; -static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_LICENSE("GPL"); @@ -2915,7 +2912,6 @@ static void mgslpc_add_device(MGSLPC_INFO *info) if (info->line < MAX_DEVICE_COUNT) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } mgslpc_device_count++; diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 7af7a7e6b9c..bee39fdfba7 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -67,7 +67,7 @@ #include <linux/major.h> #include <linux/ppdev.h> #include <linux/smp_lock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #define PP_VERSION "ppdev: user-space parallel port driver" #define CHRDEV "ppdev" @@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode) return IEEE1284_PH_FWD_IDLE; } -static int pp_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - unsigned int minor = iminor(inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; struct parport * port; void __user *argp = (void __user *)arg; @@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file, return 0; } +static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + ret = pp_do_ioctl(file, cmd, arg); + unlock_kernel(); + return ret; +} + static int pp_open (struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); @@ -745,7 +753,7 @@ static const struct file_operations pp_fops = { .read = pp_read, .write = pp_write, .poll = pp_poll, - .ioctl = pp_ioctl, + .unlocked_ioctl = pp_ioctl, .open = pp_open, .release = pp_release, }; diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 0cdfee15291..a8f68a3f14d 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -179,7 +179,7 @@ static int rio_set_real_termios(void *ptr); static void rio_hungup(void *ptr); static void rio_close(void *ptr); static int rio_chars_in_buffer(void *ptr); -static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); static int rio_init_drivers(void); static void my_hd(void *addr, int len); @@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = { static const struct file_operations rio_fw_fops = { .owner = THIS_MODULE, - .ioctl = rio_fw_ioctl, + .unlocked_ioctl = rio_fw_ioctl, }; static struct miscdevice rio_fw_device = { @@ -560,13 +560,15 @@ static void rio_close(void *ptr) -static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int rc = 0; func_enter(); /* The "dev" argument isn't used. */ + lock_kernel(); rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); + unlock_kernel(); func_exit(); return rc; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index dbefbb30ed4..d9799e2bcfb 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -144,6 +144,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +static void rtc_get_rtc_time(struct rtc_time *rtc_tm); #ifdef RTC_IRQ static unsigned int rtc_poll(struct file *file, poll_table *wait); @@ -235,7 +236,7 @@ static inline unsigned char rtc_is_updating(void) * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) */ -irqreturn_t rtc_interrupt(int irq, void *dev_id) +static irqreturn_t rtc_interrupt(int irq, void *dev_id) { /* * Can be an alarm interrupt, update complete interrupt, @@ -1303,7 +1304,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) } #endif -void rtc_get_rtc_time(struct rtc_time *rtc_tm) +static void rtc_get_rtc_time(struct rtc_time *rtc_tm) { unsigned long uip_watchdog = jiffies, flags; unsigned char ctrl; diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 4ba3aec9e1c..7b0c35207d9 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -192,7 +192,7 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err) Maybe one could implement a more efficient version by not only transferring one character at a time. */ - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; #if 0 switch(err) { @@ -226,7 +226,7 @@ static void a2232_disable_tx_interrupts(void *ptr) /* Does this here really have to be? */ local_irq_save(flags); - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; local_irq_restore(flags); } @@ -242,7 +242,7 @@ static void a2232_enable_tx_interrupts(void *ptr) /* Does this here really have to be? */ local_irq_save(flags); - port->gs.flags |= GS_TX_INTEN; + port->gs.port.flags |= GS_TX_INTEN; local_irq_restore(flags); } @@ -276,9 +276,9 @@ static void a2232_shutdown_port(void *ptr) local_irq_save(flags); - port->gs.flags &= ~GS_ACTIVE; + port->gs.port.flags &= ~GS_ACTIVE; - if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { + if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { /* Set DTR and RTS to Low, flush output. The NetBSD driver "msc.c" does it this way. */ stat->Command = ( (stat->Command & ~A2232CMD_CMask) | @@ -309,7 +309,7 @@ static int a2232_set_real_termios(void *ptr) volatile struct a2232status *status; volatile struct a2232memory *mem; - if (!port->gs.tty || !port->gs.tty->termios) return 0; + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; status = a2232stat(port->which_a2232, port->which_port_on_a2232); mem = a2232mem(port->which_a2232); @@ -345,7 +345,7 @@ static int a2232_set_real_termios(void *ptr) } a2232_param |= rate; - cflag = port->gs.tty->termios->c_cflag; + cflag = port->gs.port.tty->termios->c_cflag; // get character size chsize = cflag & CSIZE; @@ -382,7 +382,7 @@ static int a2232_set_real_termios(void *ptr) the conventional way of inserting START/STOP characters by hand in throttle()/unthrottle(). */ - softflow = !!( port->gs.tty->termios->c_iflag & IXOFF ); + softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF ); // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) parity = cflag & (PARENB | PARODD); @@ -400,9 +400,9 @@ static int a2232_set_real_termios(void *ptr) /* Hmm. Maybe an own a2232_port structure member would be cleaner? */ if (cflag & CLOCAL) - port->gs.flags &= ~ASYNC_CHECK_CD; + port->gs.port.flags &= ~ASYNC_CHECK_CD; else - port->gs.flags |= ASYNC_CHECK_CD; + port->gs.port.flags |= ASYNC_CHECK_CD; /* Now we have all parameters and can go to set them: */ @@ -482,18 +482,18 @@ static int a2232_open(struct tty_struct * tty, struct file * filp) port = &a2232_ports[line]; tty->driver_data = port; - port->gs.tty = tty; - port->gs.count++; + port->gs.port.tty = tty; + port->gs.port.count++; retval = gs_init_port(&port->gs); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } - port->gs.flags |= GS_ACTIVE; + port->gs.port.flags |= GS_ACTIVE; retval = gs_block_til_ready(port, filp); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } @@ -522,7 +522,7 @@ int ch, err, n, p; for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ err = 0; port = &a2232_ports[n*NUMLINES+p]; - if ( port->gs.flags & GS_ACTIVE ){ /* if the port is used */ + if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */ status = a2232stat(n,p); @@ -577,8 +577,8 @@ int ch, err, n, p; obuf = mem->OutBuf[p]; bufpos = status->OutHead; while ( (port->gs.xmit_cnt > 0) && - (!port->gs.tty->stopped) && - (!port->gs.tty->hw_stopped) ){ /* While there are chars to transmit */ + (!port->gs.port.tty->stopped) && + (!port->gs.port.tty->hw_stopped) ){ /* While there are chars to transmit */ if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */ @@ -592,8 +592,8 @@ int ch, err, n, p; status->OutHead = bufpos; /* WakeUp if output buffer runs low */ - if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { - tty_wakeup(port->gs.tty); + if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { + tty_wakeup(port->gs.port.tty); } } // if the port is used } // for every port on the board @@ -613,16 +613,16 @@ int ch, err, n, p; struct a2232_port *port = &a2232_ports[n*7+p]; port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ - if (!(port->gs.flags & ASYNC_CHECK_CD)) + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) ; /* Don't report DCD changes */ else if (port->cd_status) { // if DCD on: DCD went UP! /* Are we blocking in open?*/ - wake_up_interruptible(&port->gs.open_wait); + wake_up_interruptible(&port->gs.port.open_wait); } else { // if DCD off: DCD went DOWN! - if (port->gs.tty) - tty_hangup (port->gs.tty); + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); } } // if CD changed for this port @@ -655,8 +655,8 @@ static void a2232_init_portstructs(void) #ifdef NEW_WRITE_LOCKING mutex_init(&(port->gs.port_write_mutex)); #endif - init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); + init_waitqueue_head(&port->gs.port.open_wait); + init_waitqueue_head(&port->gs.port.close_wait); } } diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 2162439bbe4..c385206f9db 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -286,8 +286,8 @@ static void sx_close(void *ptr); static int sx_chars_in_buffer(void *ptr); static int sx_init_board(struct sx_board *board); static int sx_init_portstructs(int nboards, int nports); -static int sx_fw_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); static int sx_init_drivers(void); static struct tty_driver *sx_driver; @@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { static const struct file_operations sx_fw_fops = { .owner = THIS_MODULE, - .ioctl = sx_fw_ioctl, + .unlocked_ioctl = sx_fw_ioctl, }; static struct miscdevice sx_fw_device = { @@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) } #endif -static int sx_fw_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) { - int rc = 0; + long rc = 0; int __user *descr = (int __user *)arg; int i; static struct sx_board *board = NULL; @@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, func_enter(); -#if 0 - /* Removed superuser check: Sysops can use the permissions on the device - file to restrict access. Recommendation: Root only. (root.root 600) */ - if (!capable(CAP_SYS_ADMIN)) { + if (!capable(CAP_SYS_RAWIO)) return -EPERM; - } -#endif + + lock_kernel(); sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); @@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < SX_NBOARDS; i++) sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); + unlock_kernel(); return -EIO; } switch (cmd) { case SXIO_SET_BOARD: sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + rc = -EIO; if (arg >= SX_NBOARDS) - return -EIO; + break; sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); if (!(boards[arg].flags & SX_BOARD_PRESENT)) - return -EIO; + break; sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); board = &boards[arg]; + rc = 0; + /* FIXME: And this does ... nothing?? */ break; case SXIO_GET_TYPE: rc = -ENOENT; /* If we manage to miss one, return error. */ @@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = SX_TYPE_SI; if (IS_EISA_BOARD(board)) rc = SX_TYPE_SI; - sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); + sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); break; case SXIO_DO_RAMTEST: if (sx_initialized) /* Already initialized: better not ramtest the board. */ @@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = do_memtest(board, 0, 0x7ff8); /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ } - sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", - rc); + sx_dprintk(SX_DEBUG_FIRMWARE, + "returning memtest result= %ld\n", rc); break; case SXIO_DOWNLOAD: - if (sx_initialized) /* Already initialized */ - return -EEXIST; - if (!sx_reset(board)) - return -EIO; + if (sx_initialized) {/* Already initialized */ + rc = -EEXIST; + break; + } + if (!sx_reset(board)) { + rc = -EIO; + break; + } sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); - if (!tmp) - return -ENOMEM; + if (!tmp) { + rc = -ENOMEM; + break; + } + /* FIXME: check returns */ get_user(nbytes, descr++); get_user(offset, descr++); get_user(data, descr++); @@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, (i + SX_CHUNK_SIZE > nbytes) ? nbytes - i : SX_CHUNK_SIZE)) { kfree(tmp); - return -EFAULT; + rc = -EFAULT; + break; } memcpy_toio(board->base2 + offset + i, tmp, (i + SX_CHUNK_SIZE > nbytes) ? @@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = sx_nports; break; case SXIO_INIT: - if (sx_initialized) /* Already initialized */ - return -EEXIST; + if (sx_initialized) { /* Already initialized */ + rc = -EEXIST; + break; + } /* This is not allowed until all boards are initialized... */ for (i = 0; i < SX_NBOARDS; i++) { if ((boards[i].flags & SX_BOARD_PRESENT) && - !(boards[i].flags & SX_BOARD_INITIALIZED)) - return -EIO; + !(boards[i].flags & SX_BOARD_INITIALIZED)) { + rc = -EIO; + break; + } } for (i = 0; i < SX_NBOARDS; i++) if (!(boards[i].flags & SX_BOARD_PRESENT)) @@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = sx_nports; break; default: - printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", - cmd); + rc = -ENOTTY; break; } + unlock_kernel(); func_exit(); return rc; } diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ef6706f0906..500f5176b6b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -304,7 +304,6 @@ struct mgsl_struct { /* generic HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -868,7 +867,6 @@ static int irq[MAX_ISA_DEVICES]; static int dma[MAX_ISA_DEVICES]; static int debug_level; static int maxframe[MAX_TOTAL_DEVICES]; -static int dosyncppp[MAX_TOTAL_DEVICES]; static int txdmabufs[MAX_TOTAL_DEVICES]; static int txholdbufs[MAX_TOTAL_DEVICES]; @@ -879,7 +877,6 @@ module_param_array(irq, int, NULL, 0); module_param_array(dma, int, NULL, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); module_param_array(txdmabufs, int, NULL, 0); module_param_array(txholdbufs, int, NULL, 0); @@ -4258,7 +4255,6 @@ static void mgsl_add_device( struct mgsl_struct *info ) if (info->line < MAX_TOTAL_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; if (txdmabufs[info->line]) { info->num_tx_dma_buffers = txdmabufs[info->line]; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 3e9058993e4..509c89ac5bd 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -128,17 +128,14 @@ static int slgt_device_count; static int ttymajor; static int debug_level; static int maxframe[MAX_DEVICES]; -static int dosyncppp[MAX_DEVICES]; module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); -MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable"); /* * tty support and callbacks @@ -349,7 +346,6 @@ struct slgt_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC struct net_device *netdev; @@ -3405,7 +3401,6 @@ static void add_device(struct slgt_info *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } slgt_device_count++; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index c0490cbd0db..6bdb44f7bec 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -270,7 +270,6 @@ typedef struct _synclinkmp_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -469,13 +468,11 @@ static int ttymajor = 0; */ static int debug_level = 0; static int maxframe[MAX_DEVICES] = {0,}; -static int dosyncppp[MAX_DEVICES] = {0,}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); static char *driver_name = "SyncLink MultiPort driver"; static char *driver_version = "$Revision: 4.38 $"; @@ -3752,7 +3749,6 @@ static void add_device(SLMP_INFO *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } synclinkmp_device_count++; diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e1fc193d939..ae766d86845 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -580,91 +580,133 @@ void tpm_continue_selftest(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_continue_selftest); +#define TPM_INTERNAL_RESULT_SIZE 200 + ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + "attemtping to determine the permanent enabled state"); + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); + } + + rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_enabled); ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + "attemtping to determine the permanent active state"); + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); + } + + rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_active); ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[sizeof(tpm_cap)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the owner state"); - if (rc) + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); + } + + rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_owned); ssize_t tpm_show_temp_deactivated(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[sizeof(tpm_cap)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the temporary state"); - if (rc) + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); + } + + rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); @@ -678,7 +720,7 @@ static const u8 pcrread[] = { ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; + u8 *data; ssize_t rc; int i, j, num_pcrs; __be32 index; @@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the number of PCRS"); - if (rc) + if (rc) { + kfree(data); return 0; + } num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to read a PCR"); if (rc) goto out; @@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, str += sprintf(str, "\n"); } out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); @@ -795,7 +844,7 @@ static const u8 cap_version[] = { ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + u8 *data; ssize_t rc; char *str = buf; @@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the manufacturer"); - if (rc) + if (rc) { + kfree(data); return 0; + } str += sprintf(str, "Manufacturer: 0x%x\n", be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); memcpy(data, cap_version, sizeof(cap_version)); data[CAP_VERSION_IDX] = CAP_VERSION_1_1; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the 1.1 version"); if (rc) goto out; @@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, (int) data[17]); out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); @@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); ssize_t tpm_show_caps_1_2(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + u8 *data; ssize_t len; char *str = buf; @@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { + len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); + if (len <= TPM_ERROR_SIZE) { dev_dbg(chip->dev, "A TPM error (%d) occurred " "attempting to determine the manufacturer\n", be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + kfree(data); return 0; } @@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev, memcpy(data, cap_version, sizeof(cap_version)); data[CAP_VERSION_IDX] = CAP_VERSION_1_2; - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { + len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); + if (len <= TPM_ERROR_SIZE) { dev_err(chip->dev, "A TPM error (%d) occurred " "attempting to determine the 1.2 version\n", be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); @@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev, (int) data[19]); out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); @@ -966,7 +1028,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - int in_size = size, out_size; + size_t in_size = size, out_size; /* cannot perform a write until the read has cleared either via tpm_read or a user_read_timer timeout */ @@ -1001,7 +1063,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - int ret_size; + ssize_t ret_size; del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 60a2d2630e3..68f052b42ed 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c @@ -448,7 +448,7 @@ out_free: goto out; } -const struct file_operations tpm_ascii_bios_measurements_ops = { +static const struct file_operations tpm_ascii_bios_measurements_ops = { .open = tpm_ascii_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, @@ -486,7 +486,7 @@ out_free: goto out; } -const struct file_operations tpm_binary_bios_measurements_ops = { +static const struct file_operations tpm_binary_bios_measurements_ops = { .open = tpm_binary_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7a977bc03e..ed1879c0dd8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -622,6 +622,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"ATM1200", 0}, /* Atmel */ {"IFX0102", 0}, /* Infineon */ {"BCM0101", 0}, /* Broadcom */ + {"BCM0102", 0}, /* Broadcom */ {"NSC1200", 0}, /* National */ {"ICO0102", 0}, /* Intel */ /* Add new here */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6f4d856df98..e1b46bc7e43 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -3580,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p) p->signal->tty = NULL; spin_unlock_irq(&p->sighand->siglock); } -EXPORT_SYMBOL(proc_clear_tty); /* Called under the sighand lock */ diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 241cbdea65a..f307f135cbf 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -169,7 +169,7 @@ static int tty_ldisc_get(int disc, struct tty_ldisc *ld) if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; err = tty_ldisc_try_get(disc, ld); - if (err == -EAGAIN) { + if (err < 0) { request_module("tty-ldisc-%d", disc); err = tty_ldisc_try_get(disc, ld); } diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c deleted file mode 100644 index 65fb848e1cc..00000000000 --- a/drivers/char/viocons.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* -*- linux-c -*- - * - * drivers/char/viocons.c - * - * iSeries Virtual Terminal - * - * Authors: Dave Boutcher <boutcher@us.ibm.com> - * Ryan Arnold <ryanarn@us.ibm.com> - * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell - * - * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation - * - * 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) anyu later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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/kernel.h> -#include <linux/proc_fs.h> -#include <linux/errno.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/console.h> -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/init.h> -#include <linux/wait.h> -#include <linux/spinlock.h> -#include <asm/ioctls.h> -#include <linux/kd.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/sysrq.h> - -#include <asm/firmware.h> -#include <asm/iseries/vio.h> -#include <asm/iseries/hv_lp_event.h> -#include <asm/iseries/hv_call_event.h> -#include <asm/iseries/hv_lp_config.h> -#include <asm/iseries/hv_call.h> - -#ifdef CONFIG_VT -#error You must turn off CONFIG_VT to use CONFIG_VIOCONS -#endif - -#define VIOTTY_MAGIC (0x0DCB) -#define VTTY_PORTS 10 - -#define VIOCONS_KERN_WARN KERN_WARNING "viocons: " -#define VIOCONS_KERN_INFO KERN_INFO "viocons: " - -static DEFINE_SPINLOCK(consolelock); -static DEFINE_SPINLOCK(consoleloglock); - -static int vio_sysrq_pressed; - -#define VIOCHAR_NUM_BUF 16 - -/* - * Our port information. We store a pointer to one entry in the - * tty_driver_data - */ -static struct port_info { - int magic; - struct tty_struct *tty; - HvLpIndex lp; - u8 vcons; - u64 seq; /* sequence number of last HV send */ - u64 ack; /* last ack from HV */ -/* - * When we get writes faster than we can send it to the partition, - * buffer the data here. Note that used is a bit map of used buffers. - * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume - * it is a multiple of unsigned long - */ - unsigned long used; - u8 *buffer[VIOCHAR_NUM_BUF]; - int bufferBytes[VIOCHAR_NUM_BUF]; - int curbuf; - int bufferOverflow; - int overflowMessage; -} port_info[VTTY_PORTS]; - -#define viochar_is_console(pi) ((pi) == &port_info[0]) -#define viochar_port(pi) ((pi) - &port_info[0]) - -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp); - -static struct tty_driver *viotty_driver; - -static void hvlog(char *fmt, ...) -{ - int i; - unsigned long flags; - va_list args; - static char buf[256]; - - spin_lock_irqsave(&consoleloglock, flags); - va_start(args, fmt); - i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); - buf[i++] = '\r'; - HvCall_writeLogBuffer(buf, i); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -static void hvlogOutput(const char *buf, int count) -{ - unsigned long flags; - int begin; - int index; - static const char cr = '\r'; - - begin = 0; - spin_lock_irqsave(&consoleloglock, flags); - for (index = 0; index < count; index++) { - if (buf[index] == '\n') { - /* - * Start right after the last '\n' or at the zeroth - * array position and output the number of characters - * including the newline. - */ - HvCall_writeLogBuffer(&buf[begin], index - begin + 1); - begin = index + 1; - HvCall_writeLogBuffer(&cr, 1); - } - } - if ((index - begin) > 0) - HvCall_writeLogBuffer(&buf[begin], index - begin); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -/* - * Make sure we're pointing to a valid port_info structure. Shamelessly - * plagerized from serial.c - */ -static inline int viotty_paranoia_check(struct port_info *pi, - char *name, const char *routine) -{ - static const char *bad_pi_addr = VIOCONS_KERN_WARN - "warning: bad address for port_info struct (%s) in %s\n"; - static const char *badmagic = VIOCONS_KERN_WARN - "warning: bad magic number for port_info struct (%s) in %s\n"; - - if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) { - printk(bad_pi_addr, name, routine); - return 1; - } - if (pi->magic != VIOTTY_MAGIC) { - printk(badmagic, name, routine); - return 1; - } - return 0; -} - -/* - * Add data to our pending-send buffers. - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static int buffer_add(struct port_info *pi, const char *buf, size_t len) -{ - size_t bleft; - size_t curlen; - const char *curbuf; - int nextbuf; - - curbuf = buf; - bleft = len; - while (bleft > 0) { - /* - * If there is no space left in the current buffer, we have - * filled everything up, so return. If we filled the previous - * buffer we would already have moved to the next one. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n"); - pi->bufferOverflow++; - pi->overflowMessage = 1; - break; - } - - /* - * Turn on the "used" bit for this buffer. If it's already on, - * that's fine. - */ - set_bit(pi->curbuf, &pi->used); - - /* - * See if this buffer has been allocated. If not, allocate it. - */ - if (pi->buffer[pi->curbuf] == NULL) { - pi->buffer[pi->curbuf] = - kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC); - if (pi->buffer[pi->curbuf] == NULL) { - hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.", - pi->curbuf); - break; - } - } - - /* Figure out how much we can copy into this buffer. */ - if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf])) - curlen = bleft; - else - curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]; - - /* Copy the data into the buffer. */ - memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf], - curbuf, curlen); - - pi->bufferBytes[pi->curbuf] += curlen; - curbuf += curlen; - bleft -= curlen; - - /* - * Now see if we've filled this buffer. If not then - * we'll try to use it again later. If we've filled it - * up then we'll advance the curbuf to the next in the - * circular queue. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - /* - * Move to the next buffer if it hasn't been used yet - */ - if (test_bit(nextbuf, &pi->used) == 0) - pi->curbuf = nextbuf; - } - } - return len - bleft; -} - -/* - * Send pending data - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static void send_buffers(struct port_info *pi) -{ - HvLpEvent_Rc hvrc; - int nextbuf; - struct viocharlpevent *viochar; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - - viochar = (struct viocharlpevent *) - vio_get_event_buffer(viomajorsubtype_chario); - - /* Make sure we got a buffer */ - if (viochar == NULL) { - hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers()."); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - if (pi->used == 0) { - hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n"); - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - /* - * curbuf points to the buffer we're filling. We want to - * start sending AFTER this one. - */ - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - - /* - * Loop until we find a buffer with the used bit on - */ - while (test_bit(nextbuf, &pi->used) == 0) - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - - initDataEvent(viochar, pi->lp); - - /* - * While we have buffers with data, and our send window - * is open, send them - */ - while ((test_bit(nextbuf, &pi->used)) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - viochar->len = pi->bufferBytes[nextbuf]; - viochar->event.xCorrelationToken = pi->seq++; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + viochar->len; - - memcpy(viochar->data, pi->buffer[nextbuf], viochar->len); - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - /* - * MUST unlock the spinlock before doing a printk - */ - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - - printk(VIOCONS_KERN_WARN - "error sending event! return code %d\n", - (int)hvrc); - return; - } - - /* - * clear the used bit, zero the number of bytes in - * this buffer, and move to the next buffer - */ - clear_bit(nextbuf, &pi->used); - pi->bufferBytes[nextbuf] = 0; - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - } - - /* - * If we have emptied all the buffers, start at 0 again. - * this will re-use any allocated buffers - */ - if (pi->used == 0) { - pi->curbuf = 0; - - if (pi->overflowMessage) - pi->overflowMessage = 0; - - if (pi->tty) { - tty_wakeup(pi->tty); - } - } - - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * Our internal writer. Gets called both from the console device and - * the tty device. the tty pointer will be NULL if called from the console. - * Return total number of bytes "written". - * - * NOTE: Don't use printk in here because it gets nastily recursive. hvlog - * can be used to log to the hypervisor buffer - */ -static int internal_write(struct port_info *pi, const char *buf, size_t len) -{ - HvLpEvent_Rc hvrc; - size_t bleft; - size_t curlen; - const char *curbuf; - unsigned long flags; - struct viocharlpevent *viochar; - - /* - * Write to the hvlog of inbound data are now done prior to - * calling internal_write() since internal_write() is only called in - * the event that an lp event path is active, which isn't the case for - * logging attempts prior to console initialization. - * - * If there is already data queued for this port, send it prior to - * attempting to send any new data. - */ - if (pi->used) - send_buffers(pi); - - spin_lock_irqsave(&consolelock, flags); - - viochar = vio_get_event_buffer(viomajorsubtype_chario); - if (viochar == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - hvlog("\n\rviocons: Can't get vio buffer in internal_write()."); - return -EAGAIN; - } - initDataEvent(viochar, pi->lp); - - curbuf = buf; - bleft = len; - - while ((bleft > 0) && (pi->used == 0) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - if (bleft > VIOCHAR_MAX_DATA) - curlen = VIOCHAR_MAX_DATA; - else - curlen = bleft; - - viochar->event.xCorrelationToken = pi->seq++; - memcpy(viochar->data, curbuf, curlen); - viochar->len = curlen; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + curlen; - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - hvlog("viocons: error sending event! %d\n", (int)hvrc); - goto out; - } - curbuf += curlen; - bleft -= curlen; - } - - /* If we didn't send it all, buffer as much of it as we can. */ - if (bleft > 0) - bleft -= buffer_add(pi, curbuf, bleft); -out: - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return len - bleft; -} - -static struct port_info *get_port_data(struct tty_struct *tty) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - if (tty) { - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, - "get_port_data")) { - pi = NULL; - } - } else - /* - * If this is the console device, use the lp from - * the first port entry - */ - pi = &port_info[0]; - spin_unlock_irqrestore(&consolelock, flags); - return pi; -} - -/* - * Initialize the common fields in a charLpEvent - */ -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) -{ - struct HvLpEvent *hev = &viochar->event; - - memset(viochar, 0, sizeof(struct viocharlpevent)); - - hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | - HV_LP_EVENT_INT; - hev->xType = HvLpEvent_Type_VirtualIo; - hev->xSubtype = viomajorsubtype_chario | viochardata; - hev->xSourceLp = HvLpConfig_getLpIndex(); - hev->xTargetLp = lp; - hev->xSizeMinus1 = sizeof(struct viocharlpevent); - hev->xSourceInstanceId = viopath_sourceinst(lp); - hev->xTargetInstanceId = viopath_targetinst(lp); -} - -/* - * early console device write - */ -static void viocons_write_early(struct console *co, const char *s, unsigned count) -{ - hvlogOutput(s, count); -} - -/* - * console device write - */ -static void viocons_write(struct console *co, const char *s, unsigned count) -{ - int index; - int begin; - struct port_info *pi; - - static const char cr = '\r'; - - /* - * Check port data first because the target LP might be valid but - * simply not active, in which case we want to hvlog the output. - */ - pi = get_port_data(NULL); - if (pi == NULL) { - hvlog("\n\rviocons_write: unable to get port data."); - return; - } - - hvlogOutput(s, count); - - if (!viopath_isactive(pi->lp)) - return; - - /* - * Any newline character found will cause a - * carriage return character to be emitted as well. - */ - begin = 0; - for (index = 0; index < count; index++) { - if (s[index] == '\n') { - /* - * Newline found. Print everything up to and - * including the newline - */ - internal_write(pi, &s[begin], index - begin + 1); - begin = index + 1; - /* Emit a carriage return as well */ - internal_write(pi, &cr, 1); - } - } - - /* If any characters left to write, write them now */ - if ((index - begin) > 0) - internal_write(pi, &s[begin], index - begin); -} - -/* - * Work out the device associate with this console - */ -static struct tty_driver *viocons_device(struct console *c, int *index) -{ - *index = c->index; - return viotty_driver; -} - -/* - * console device I/O methods - */ -static struct console viocons_early = { - .name = "viocons", - .write = viocons_write_early, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static struct console viocons = { - .name = "viocons", - .write = viocons_write, - .device = viocons_device, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * TTY Open method - */ -static int viotty_open(struct tty_struct *tty, struct file *filp) -{ - int port; - unsigned long flags; - struct port_info *pi; - - port = tty->index; - - if ((port < 0) || (port >= VTTY_PORTS)) - return -ENODEV; - - spin_lock_irqsave(&consolelock, flags); - - pi = &port_info[port]; - /* If some other TTY is already connected here, reject the open */ - if ((pi->tty) && (pi->tty != tty)) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN - "attempt to open device twice from different ttys\n"); - return -EBUSY; - } - tty->driver_data = pi; - pi->tty = tty; - spin_unlock_irqrestore(&consolelock, flags); - - return 0; -} - -/* - * TTY Close method - */ -static void viotty_close(struct tty_struct *tty, struct file *filp) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - if (tty->count == 1) - pi->tty = NULL; - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * TTY Write method - */ -static int viotty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) { - hvlog("\n\rviotty_write: no port data."); - return -ENODEV; - } - - if (viochar_is_console(pi)) - hvlogOutput(buf, count); - - /* - * If the path to this LP is closed, don't bother doing anything more. - * just dump the data on the floor and return count. For some reason - * some user level programs will attempt to probe available tty's and - * they'll attempt a viotty_write on an invalid port which maps to an - * invalid target lp. If this is the case then ignore the - * viotty_write call and, since the viopath isn't active to this - * partition, return count. - */ - if (!viopath_isactive(pi->lp)) - return count; - - return internal_write(pi, buf, count); -} - -/* - * TTY put_char method - */ -static int viotty_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) - return 0; - - /* This will append '\r' as well if the char is '\n' */ - if (viochar_is_console(pi)) - hvlogOutput(&ch, 1); - - if (viopath_isactive(pi->lp)) - internal_write(pi, &ch, 1); - return 1; -} - -/* - * TTY write_room method - */ -static int viotty_write_room(struct tty_struct *tty) -{ - int i; - int room = 0; - struct port_info *pi; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) { - spin_unlock_irqrestore(&consolelock, flags); - return 0; - } - - /* If no buffers are used, return the max size. */ - if (pi->used == 0) { - spin_unlock_irqrestore(&consolelock, flags); - return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF; - } - - /* - * We retain the spinlock because we want to get an accurate - * count and it can change on us between each operation if we - * don't hold the spinlock. - */ - for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++) - room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]); - spin_unlock_irqrestore(&consolelock, flags); - - if (room > VIOCHAR_MAX_DATA) - room = VIOCHAR_MAX_DATA; - return room; -} - -/* - * TTY chars_in_buffer method - */ -static int viotty_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -static int viotty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - /* - * the ioctls below read/set the flags usually shown in the leds - * don't use them - they will go away without warning - */ - case KDGETLED: - case KDGKBLED: - return put_user(0, (char *)arg); - - case KDSKBLED: - return 0; - } - /* FIXME: WTF is this being called for ??? */ - lock_kernel(); - ret = n_tty_ioctl(tty, file, cmd, arg); - unlock_kernel(); - return ret; -} - -/* - * Handle an open charLpEvent. Could be either interrupt or ack - */ -static void vioHandleOpenEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - struct port_info *pi; - int reject = 0; - - if (hvlpevent_is_ack(event)) { - if (port >= VTTY_PORTS) - return; - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - pi = &port_info[port]; - if (event->xRc == HvLpEvent_Rc_Good) { - pi->seq = pi->ack = 0; - /* - * This line allows connections from the primary - * partition but once one is connected from the - * primary partition nothing short of a reboot - * of linux will allow access from the hosting - * partition again without a required iSeries fix. - */ - pi->lp = event->xTargetLp; - } - - spin_unlock_irqrestore(&consolelock, flags); - if (event->xRc != HvLpEvent_Rc_Good) - printk(VIOCONS_KERN_WARN - "handle_open_event: event->xRc == (%d).\n", - event->xRc); - - if (event->xCorrelationToken != 0) { - atomic_t *aptr= (atomic_t *)event->xCorrelationToken; - atomic_set(aptr, 1); - } else - printk(VIOCONS_KERN_WARN - "weird...got open ack without atomic\n"); - return; - } - - /* This had better require an ack, otherwise complain */ - if (!hvlpevent_need_ack(event)) { - printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - /* Make sure this is a good virtual tty */ - if (port >= VTTY_PORTS) { - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - /* - * Flag state here since we can't printk while holding - * a spinlock. - */ - reject = 1; - } else { - pi = &port_info[port]; - if ((pi->lp != HvLpIndexInvalid) && - (pi->lp != event->xSourceLp)) { - /* - * If this is tty is already connected to a different - * partition, fail. - */ - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - reject = 2; - } else { - pi->lp = event->xSourceLp; - event->xRc = HvLpEvent_Rc_Good; - cevent->subtype_result_code = viorc_good; - pi->seq = pi->ack = 0; - reject = 0; - } - } - - spin_unlock_irqrestore(&consolelock, flags); - - if (reject == 1) - printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n"); - else if (reject == 2) - printk(VIOCONS_KERN_WARN - "open rejected: console in exclusive use by another partition.\n"); - - /* Return the acknowledgement */ - HvCallEvent_ackLpEvent(event); -} - -/* - * Handle a close charLpEvent. This should ONLY be an Interrupt because the - * virtual console should never actually issue a close event to the hypervisor - * because the virtual console never goes away. A close event coming from the - * hypervisor simply means that there are no client consoles connected to the - * virtual console. - * - * Regardless of the number of connections masqueraded on the other side of - * the hypervisor ONLY ONE close event should be called to accompany the ONE - * open event that is called. The close event should ONLY be called when NO - * MORE connections (masqueraded or not) exist on the other side of the - * hypervisor. - */ -static void vioHandleCloseEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - - if (hvlpevent_is_int(event)) { - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN - "close message from invalid virtual device.\n"); - return; - } - - /* For closes, just mark the console partition invalid */ - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - if (port_info[port].lp == event->xSourceLp) - port_info[port].lp = HvLpIndexInvalid; - - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp); - } else - printk(VIOCONS_KERN_WARN - "got unexpected close acknowlegement\n"); -} - -/* - * Handle a config charLpEvent. Could be either interrupt or ack - */ -static void vioHandleConfig(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - - HvCall_writeLogBuffer(cevent->data, cevent->len); - - if (cevent->data[0] == 0x01) - printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n", - cevent->data[1], cevent->data[2], - cevent->data[3], cevent->data[4]); - else - printk(VIOCONS_KERN_WARN "unknown config event\n"); -} - -/* - * Handle a data charLpEvent. - */ -static void vioHandleData(struct HvLpEvent *event) -{ - struct tty_struct *tty; - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - struct port_info *pi; - int index; - int num_pushed; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n", - port); - return; - } - - /* - * Hold the spinlock so that we don't take an interrupt that - * changes tty between the time we fetch the port_info - * pointer and the time we paranoia check. - */ - spin_lock_irqsave(&consolelock, flags); - pi = &port_info[port]; - - /* - * Change 05/01/2003 - Ryan Arnold: If a partition other than - * the current exclusive partition tries to send us data - * events then just drop them on the floor because we don't - * want his stinking data. He isn't authorized to receive - * data because he wasn't the first one to get the console, - * therefore he shouldn't be allowed to send data either. - * This will work without an iSeries fix. - */ - if (pi->lp != event->xSourceLp) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - tty = pi->tty; - if (tty == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n", - port); - return; - } - - if (tty->magic != TTY_MAGIC) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "tty bad magic\n"); - return; - } - - /* - * Just to be paranoid, make sure the tty points back to this port - */ - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - spin_unlock_irqrestore(&consolelock, flags); - - /* - * Change 07/21/2003 - Ryan Arnold: functionality added to - * support sysrq utilizing ^O as the sysrq key. The sysrq - * functionality will only work if built into the kernel and - * then only if sysrq is enabled through the proc filesystem. - */ - num_pushed = 0; - for (index = 0; index < cevent->len; index++) { - /* - * Will be optimized away if !CONFIG_MAGIC_SYSRQ: - */ - if (sysrq_on()) { - /* 0x0f is the ascii character for ^O */ - if (cevent->data[index] == '\x0f') { - vio_sysrq_pressed = 1; - /* - * continue because we don't want to add - * the sysrq key into the data string. - */ - continue; - } else if (vio_sysrq_pressed) { - handle_sysrq(cevent->data[index], tty); - vio_sysrq_pressed = 0; - /* - * continue because we don't want to add - * the sysrq sequence into the data string. - */ - continue; - } - } - /* - * The sysrq sequence isn't included in this check if - * sysrq is enabled and compiled into the kernel because - * the sequence will never get inserted into the buffer. - * Don't attempt to copy more data into the buffer than we - * have room for because it would fail without indication. - */ - if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) { - printk(VIOCONS_KERN_WARN "input buffer overflow!\n"); - break; - } - num_pushed++; - } - - if (num_pushed) - tty_flip_buffer_push(tty); -} - -/* - * Handle an ack charLpEvent. - */ -static void vioHandleAck(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - unsigned long flags; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - port_info[port].ack = event->xCorrelationToken; - spin_unlock_irqrestore(&consolelock, flags); - - if (port_info[port].used) - send_buffers(&port_info[port]); -} - -/* - * Handle charLpEvents and route to the appropriate routine - */ -static void vioHandleCharEvent(struct HvLpEvent *event) -{ - int charminor; - - if (event == NULL) - return; - - charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; - switch (charminor) { - case viocharopen: - vioHandleOpenEvent(event); - break; - case viocharclose: - vioHandleCloseEvent(event); - break; - case viochardata: - vioHandleData(event); - break; - case viocharack: - vioHandleAck(event); - break; - case viocharconfig: - vioHandleConfig(event); - break; - default: - if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - } -} - -/* - * Send an open event - */ -static int send_open(HvLpIndex remoteLp, void *sem) -{ - return HvCallEvent_signalLpEventFast(remoteLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_chario | viocharopen, - HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, - viopath_sourceinst(remoteLp), - viopath_targetinst(remoteLp), - (u64)(unsigned long)sem, VIOVERSION << 16, - 0, 0, 0, 0); -} - -static const struct tty_operations serial_ops = { - .open = viotty_open, - .close = viotty_close, - .write = viotty_write, - .put_char = viotty_put_char, - .write_room = viotty_write_room, - .chars_in_buffer = viotty_chars_in_buffer, - .ioctl = viotty_ioctl, -}; - -static int __init viocons_init2(void) -{ - atomic_t wait_flag; - int rc; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - /* +2 for fudge */ - rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), - viomajorsubtype_chario, VIOCHAR_WINDOW + 2); - if (rc) - printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc); - - if (viopath_hostLp == HvLpIndexInvalid) - vio_set_hostlp(); - - /* - * And if the primary is not the same as the hosting LP, open to the - * hosting lp - */ - if ((viopath_hostLp != HvLpIndexInvalid) && - (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) { - printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n", - viopath_hostLp); - rc = viopath_open(viopath_hostLp, viomajorsubtype_chario, - VIOCHAR_WINDOW + 2); /* +2 for fudge */ - if (rc) - printk(VIOCONS_KERN_WARN - "error opening to partition %d: %d\n", - viopath_hostLp, rc); - } - - if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0) - printk(VIOCONS_KERN_WARN - "error seting handler for console events!\n"); - - /* - * First, try to open the console to the hosting lp. - * Wait on a semaphore for the response. - */ - atomic_set(&wait_flag, 0); - if ((viopath_isactive(viopath_hostLp)) && - (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) { - printk(VIOCONS_KERN_INFO "hosting partition %d\n", - viopath_hostLp); - while (atomic_read(&wait_flag) == 0) - mb(); - atomic_set(&wait_flag, 0); - } - - /* - * If we don't have an active console, try the primary - */ - if ((!viopath_isactive(port_info[0].lp)) && - (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) && - (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag) - == 0)) { - printk(VIOCONS_KERN_INFO "opening console to primary partition\n"); - while (atomic_read(&wait_flag) == 0) - mb(); - } - - /* Initialize the tty_driver structure */ - viotty_driver = alloc_tty_driver(VTTY_PORTS); - viotty_driver->owner = THIS_MODULE; - viotty_driver->driver_name = "vioconsole"; - viotty_driver->name = "tty"; - viotty_driver->name_base = 1; - viotty_driver->major = TTY_MAJOR; - viotty_driver->minor_start = 1; - viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE; - viotty_driver->subtype = 1; - viotty_driver->init_termios = tty_std_termios; - viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - tty_set_operations(viotty_driver, &serial_ops); - - if (tty_register_driver(viotty_driver)) { - printk(VIOCONS_KERN_WARN "couldn't register console driver\n"); - put_tty_driver(viotty_driver); - viotty_driver = NULL; - } - - unregister_console(&viocons_early); - register_console(&viocons); - - return 0; -} - -static int __init viocons_init(void) -{ - int i; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - printk(VIOCONS_KERN_INFO "registering console\n"); - for (i = 0; i < VTTY_PORTS; i++) { - port_info[i].lp = HvLpIndexInvalid; - port_info[i].magic = VIOTTY_MAGIC; - } - HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437); - add_preferred_console("viocons", 0, NULL); - register_console(&viocons_early); - return 0; -} - -console_initcall(viocons_init); -module_init(viocons_init2); diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index dc17fe3a88b..d0f4eb6fdb7 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -46,6 +46,9 @@ static char *in, *inbuf; /* The operations for our console. */ static struct hv_ops virtio_cons; +/* The hvc device */ +static struct hvc_struct *hvc; + /*D:310 The put_chars() callback is pretty straightforward. * * We turn the characters into a scatter-gather list, add it to the output @@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) return hvc_instantiate(0, 0, &virtio_cons); } +/* + * we support only one console, the hvc struct is a global var + * There is no need to do anything + */ +static int notifier_add_vio(struct hvc_struct *hp, int data) +{ + hp->irq_requested = 1; + return 0; +} + +static void notifier_del_vio(struct hvc_struct *hp, int data) +{ + hp->irq_requested = 0; +} + +static void hvc_handle_input(struct virtqueue *vq) +{ + if (hvc_poll(hvc)) + hvc_kick(); +} + /*D:370 Once we're further in boot, we get probed like any other virtio device. * At this stage we set up the output virtqueue. * @@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) static int __devinit virtcons_probe(struct virtio_device *dev) { int err; - struct hvc_struct *hvc; vdev = dev; @@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) /* Find the input queue. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq(vdev, 0, NULL); + in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input); if (IS_ERR(in_vq)) { err = PTR_ERR(in_vq); goto free; @@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev) /* Start using the new console output. */ virtio_cons.get_chars = get_chars; virtio_cons.put_chars = put_chars; + virtio_cons.notifier_add = notifier_add_vio; + virtio_cons.notifier_del = notifier_del_vio; /* The first argument of hvc_alloc() is the virtual console number, so - * we use zero. The second argument is the interrupt number; we - * currently leave this as zero: it would be better not to use the - * hvc mechanism and fix this (FIXME!). + * we use zero. The second argument is the parameter for the + * notification mechanism (like irq number). We currently leave this + * as zero, virtqueues have implicit notifications. * * The third argument is a "struct hv_ops" containing the put_chars() - * and get_chars() pointers. The final argument is the output buffer - * size: we can do any size, so we put PAGE_SIZE here. */ + * get_chars(), notifier_add() and notifier_del() pointers. + * The final argument is the output buffer size: we can do any size, + * so we put PAGE_SIZE here. */ hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); if (IS_ERR(hvc)) { err = PTR_ERR(hvc); diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 69c5afe97f1..1718b3c481d 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -183,8 +183,8 @@ static void scc_init_portstructs(void) #ifdef NEW_WRITE_LOCKING port->gs.port_write_mutex = MUTEX; #endif - init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); + init_waitqueue_head(&port->gs.port.open_wait); + init_waitqueue_head(&port->gs.port.close_wait); } } @@ -422,7 +422,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) { unsigned char ch; struct scc_port *port = data; - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; SCC_ACCESS_INIT(port); ch = SCCread_NB(RX_DATA_REG); @@ -453,7 +453,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) static irqreturn_t scc_spcond_int(int irq, void *data) { struct scc_port *port = data; - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; unsigned char stat, ch, err; int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX; @@ -500,7 +500,7 @@ static irqreturn_t scc_tx_int(int irq, void *data) struct scc_port *port = data; SCC_ACCESS_INIT(port); - if (!port->gs.tty) { + if (!port->gs.port.tty) { printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); @@ -512,8 +512,9 @@ static irqreturn_t scc_tx_int(int irq, void *data) SCCwrite(TX_DATA_REG, port->x_char); port->x_char = 0; } - else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || - port->gs.tty->hw_stopped) + else if ((port->gs.xmit_cnt <= 0) || + port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) break; else { SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); @@ -522,15 +523,15 @@ static irqreturn_t scc_tx_int(int irq, void *data) break; } } - if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || - port->gs.tty->hw_stopped) { + if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) { /* disable tx interrupts */ SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; } - if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) - tty_wakeup(port->gs.tty); + if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) + tty_wakeup(port->gs.port.tty); SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); return IRQ_HANDLED; @@ -550,14 +551,14 @@ static irqreturn_t scc_stat_int(int irq, void *data) if (changed & SR_DCD) { port->c_dcd = !!(sr & SR_DCD); - if (!(port->gs.flags & ASYNC_CHECK_CD)) + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) ; /* Don't report DCD changes */ else if (port->c_dcd) { - wake_up_interruptible(&port->gs.open_wait); + wake_up_interruptible(&port->gs.port.open_wait); } else { - if (port->gs.tty) - tty_hangup (port->gs.tty); + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); } } SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); @@ -578,7 +579,7 @@ static void scc_disable_tx_interrupts(void *ptr) local_irq_save(flags); SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; local_irq_restore(flags); } @@ -636,8 +637,8 @@ static void scc_shutdown_port(void *ptr) { struct scc_port *port = ptr; - port->gs.flags &= ~ GS_ACTIVE; - if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { + port->gs.port.flags &= ~ GS_ACTIVE; + if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { scc_setsignals (port, 0, 0); } } @@ -652,14 +653,14 @@ static int scc_set_real_termios (void *ptr) struct scc_port *port = ptr; SCC_ACCESS_INIT(port); - if (!port->gs.tty || !port->gs.tty->termios) return 0; + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; channel = port->channel; if (channel == CHANNEL_A) return 0; /* Settings controlled by boot PROM */ - cflag = port->gs.tty->termios->c_cflag; + cflag = port->gs.port.tty->termios->c_cflag; baud = port->gs.baud; chsize = (cflag & CSIZE) >> 4; @@ -678,9 +679,9 @@ static int scc_set_real_termios (void *ptr) } if (cflag & CLOCAL) - port->gs.flags &= ~ASYNC_CHECK_CD; + port->gs.port.flags &= ~ASYNC_CHECK_CD; else - port->gs.flags |= ASYNC_CHECK_CD; + port->gs.port.flags |= ASYNC_CHECK_CD; #ifdef CONFIG_MVME147_SCC if (MACH_IS_MVME147) @@ -856,7 +857,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) { COMMAND_REG, CR_EXTSTAT_RESET }, }; #endif - if (!(port->gs.flags & ASYNC_INITIALIZED)) { + if (!(port->gs.port.flags & ASYNC_INITIALIZED)) { local_irq_save(flags); #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) if (MACH_IS_MVME147 || MACH_IS_MVME16x) { @@ -880,18 +881,18 @@ static int scc_open (struct tty_struct * tty, struct file * filp) } tty->driver_data = port; - port->gs.tty = tty; - port->gs.count++; + port->gs.port.tty = tty; + port->gs.port.count++; retval = gs_init_port(&port->gs); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } - port->gs.flags |= GS_ACTIVE; + port->gs.port.flags |= GS_ACTIVE; retval = gs_block_til_ready(port, filp); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index cb8c90da393..1bc00c9d860 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -916,7 +916,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) ws.ws_col = vc->vc_cols; ws.ws_ypixel = vc->vc_scan_lines; - mutex_lock(&vc->vc_tty->termios_mutex); spin_lock_irq(&vc->vc_tty->ctrl_lock); if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) pgrp = get_pid(vc->vc_tty->pgrp); @@ -926,7 +925,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) put_pid(pgrp); } *cws = ws; - mutex_unlock(&vc->vc_tty->termios_mutex); } if (CON_IS_VISIBLE(vc)) @@ -2211,7 +2209,7 @@ rescan_last_byte: c = 0xfffd; tc = c; } else { /* no utf or alternate charset mode */ - tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; + tc = vc_translate(vc, c); } param.c = tc; diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 51966ccf4ea..8bfee5fb722 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -87,7 +87,6 @@ #include <linux/mutex.h> #include <linux/smp_lock.h> #include <linux/sysctl.h> -#include <linux/version.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/platform_device.h> |