diff options
Diffstat (limited to 'drivers/char')
80 files changed, 3264 insertions, 2813 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 650e6b44ce65..d0ac944e1696 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -36,6 +36,14 @@ config VT | |||
36 | If unsure, say Y, or else you won't be able to do much with your new | 36 | If unsure, say Y, or else you won't be able to do much with your new |
37 | shiny Linux system :-) | 37 | shiny Linux system :-) |
38 | 38 | ||
39 | config CONSOLE_TRANSLATIONS | ||
40 | depends on VT | ||
41 | default y | ||
42 | bool "Enable character translations in console" if EMBEDDED | ||
43 | ---help--- | ||
44 | This enables support for font mapping and Unicode translation | ||
45 | on virtual consoles. | ||
46 | |||
39 | config VT_CONSOLE | 47 | config VT_CONSOLE |
40 | bool "Support for console on virtual terminal" if EMBEDDED | 48 | bool "Support for console on virtual terminal" if EMBEDDED |
41 | depends on VT | 49 | depends on VT |
@@ -300,16 +308,6 @@ config SPECIALIX | |||
300 | and compile this driver as kernel loadable module which will be | 308 | and compile this driver as kernel loadable module which will be |
301 | called specialix. | 309 | called specialix. |
302 | 310 | ||
303 | config SPECIALIX_RTSCTS | ||
304 | bool "Specialix DTR/RTS pin is RTS" | ||
305 | depends on SPECIALIX | ||
306 | help | ||
307 | The Specialix IO8+ card can only support either RTS or DTR. If you | ||
308 | say N here, the driver will use the pin as "DTR" when the tty is in | ||
309 | software handshake mode. If you say Y here or hardware handshake is | ||
310 | on, it will always be RTS. Read the file | ||
311 | <file:Documentation/specialix.txt> for more information. | ||
312 | |||
313 | config SX | 311 | config SX |
314 | tristate "Specialix SX (and SI) card support" | 312 | tristate "Specialix SX (and SI) card support" |
315 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) | 313 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) |
@@ -588,11 +586,14 @@ config HVC_DRIVER | |||
588 | It will automatically be selected if one of the back-end console drivers | 586 | It will automatically be selected if one of the back-end console drivers |
589 | is selected. | 587 | is selected. |
590 | 588 | ||
589 | config HVC_IRQ | ||
590 | bool | ||
591 | 591 | ||
592 | config HVC_CONSOLE | 592 | config HVC_CONSOLE |
593 | bool "pSeries Hypervisor Virtual Console support" | 593 | bool "pSeries Hypervisor Virtual Console support" |
594 | depends on PPC_PSERIES | 594 | depends on PPC_PSERIES |
595 | select HVC_DRIVER | 595 | select HVC_DRIVER |
596 | select HVC_IRQ | ||
596 | help | 597 | help |
597 | pSeries machines when partitioned support a hypervisor virtual | 598 | pSeries machines when partitioned support a hypervisor virtual |
598 | console. This driver allows each pSeries partition to have a console | 599 | console. This driver allows each pSeries partition to have a console |
@@ -603,6 +604,7 @@ config HVC_ISERIES | |||
603 | depends on PPC_ISERIES | 604 | depends on PPC_ISERIES |
604 | default y | 605 | default y |
605 | select HVC_DRIVER | 606 | select HVC_DRIVER |
607 | select HVC_IRQ | ||
606 | help | 608 | help |
607 | iSeries machines support a hypervisor virtual console. | 609 | iSeries machines support a hypervisor virtual console. |
608 | 610 | ||
@@ -624,13 +626,18 @@ config HVC_XEN | |||
624 | bool "Xen Hypervisor Console support" | 626 | bool "Xen Hypervisor Console support" |
625 | depends on XEN | 627 | depends on XEN |
626 | select HVC_DRIVER | 628 | select HVC_DRIVER |
629 | select HVC_IRQ | ||
627 | default y | 630 | default y |
628 | help | 631 | help |
629 | Xen virtual console device driver | 632 | Xen virtual console device driver |
630 | 633 | ||
631 | config VIRTIO_CONSOLE | 634 | config VIRTIO_CONSOLE |
632 | bool | 635 | tristate "Virtio console" |
636 | depends on VIRTIO | ||
633 | select HVC_DRIVER | 637 | select HVC_DRIVER |
638 | help | ||
639 | Virtio console for use with lguest and other hypervisors. | ||
640 | |||
634 | 641 | ||
635 | config HVCS | 642 | config HVCS |
636 | tristate "IBM Hypervisor Virtual Console Server support" | 643 | tristate "IBM Hypervisor Virtual Console Server support" |
@@ -867,13 +874,6 @@ config DS1302 | |||
867 | 874 | ||
868 | endif # RTC_LIB | 875 | endif # RTC_LIB |
869 | 876 | ||
870 | config COBALT_LCD | ||
871 | bool "Support for Cobalt LCD" | ||
872 | depends on MIPS_COBALT | ||
873 | help | ||
874 | This option enables support for the LCD display and buttons found | ||
875 | on Cobalt systems through a misc device. | ||
876 | |||
877 | config DTLK | 877 | config DTLK |
878 | tristate "Double Talk PC internal speech card support" | 878 | tristate "Double Talk PC internal speech card support" |
879 | depends on ISA | 879 | depends on ISA |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 0e0d12a06462..8a161c30e1dc 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -7,13 +7,13 @@ | |||
7 | # | 7 | # |
8 | FONTMAPFILE = cp437.uni | 8 | FONTMAPFILE = cp437.uni |
9 | 9 | ||
10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o | 10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o |
11 | 11 | ||
12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
14 | obj-y += misc.o | 14 | obj-y += misc.o |
15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ | 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o |
16 | consolemap_deftbl.o selection.o keyboard.o | 16 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
18 | obj-$(CONFIG_AUDIT) += tty_audit.o | 18 | obj-$(CONFIG_AUDIT) += tty_audit.o |
19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
@@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | |||
48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | 49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o | ||
51 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o | 52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o |
52 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o | 53 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o |
53 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 54 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
@@ -63,7 +64,6 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o | |||
63 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o | 64 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o |
64 | 65 | ||
65 | obj-$(CONFIG_PRINTER) += lp.o | 66 | obj-$(CONFIG_PRINTER) += lp.o |
66 | obj-$(CONFIG_TIPAR) += tipar.o | ||
67 | 67 | ||
68 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o | 68 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o |
69 | 69 | ||
@@ -88,7 +88,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o | |||
88 | obj-$(CONFIG_I8K) += i8k.o | 88 | obj-$(CONFIG_I8K) += i8k.o |
89 | obj-$(CONFIG_DS1620) += ds1620.o | 89 | obj-$(CONFIG_DS1620) += ds1620.o |
90 | obj-$(CONFIG_HW_RANDOM) += hw_random/ | 90 | obj-$(CONFIG_HW_RANDOM) += hw_random/ |
91 | obj-$(CONFIG_COBALT_LCD) += lcd.o | ||
92 | obj-$(CONFIG_PPDEV) += ppdev.o | 91 | obj-$(CONFIG_PPDEV) += ppdev.o |
93 | obj-$(CONFIG_NWBUTTON) += nwbutton.o | 92 | obj-$(CONFIG_NWBUTTON) += nwbutton.o |
94 | obj-$(CONFIG_NWFLASH) += nwflash.o | 93 | obj-$(CONFIG_NWFLASH) += nwflash.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 37457e5a4f2b..3530ff417a51 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
1248 | /* | 1248 | /* |
1249 | * rs_break() --- routine which turns the break handling on or off | 1249 | * rs_break() --- routine which turns the break handling on or off |
1250 | */ | 1250 | */ |
1251 | static void rs_break(struct tty_struct *tty, int break_state) | 1251 | static int rs_break(struct tty_struct *tty, int break_state) |
1252 | { | 1252 | { |
1253 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1253 | struct async_struct * info = (struct async_struct *)tty->driver_data; |
1254 | unsigned long flags; | 1254 | unsigned long flags; |
@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state) | |||
1263 | custom.adkcon = AC_UARTBRK; | 1263 | custom.adkcon = AC_UARTBRK; |
1264 | mb(); | 1264 | mb(); |
1265 | local_irq_restore(flags); | 1265 | local_irq_restore(flags); |
1266 | return 0; | ||
1266 | } | 1267 | } |
1267 | 1268 | ||
1268 | 1269 | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e991dc85f2fb..fe6d774fe2e4 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3700 | /* | 3700 | /* |
3701 | * cy_break() --- routine which turns the break handling on or off | 3701 | * cy_break() --- routine which turns the break handling on or off |
3702 | */ | 3702 | */ |
3703 | static void cy_break(struct tty_struct *tty, int break_state) | 3703 | static int cy_break(struct tty_struct *tty, int break_state) |
3704 | { | 3704 | { |
3705 | struct cyclades_port *info = tty->driver_data; | 3705 | struct cyclades_port *info = tty->driver_data; |
3706 | struct cyclades_card *card; | 3706 | struct cyclades_card *card; |
3707 | unsigned long flags; | 3707 | unsigned long flags; |
3708 | int retval = 0; | ||
3708 | 3709 | ||
3709 | if (serial_paranoia_check(info, tty->name, "cy_break")) | 3710 | if (serial_paranoia_check(info, tty->name, "cy_break")) |
3710 | return; | 3711 | return -EINVAL; |
3711 | 3712 | ||
3712 | card = info->card; | 3713 | card = info->card; |
3713 | 3714 | ||
@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state) | |||
3736 | } | 3737 | } |
3737 | } | 3738 | } |
3738 | } else { | 3739 | } else { |
3739 | int retval; | ||
3740 | |||
3741 | if (break_state == -1) { | 3740 | if (break_state == -1) { |
3742 | retval = cyz_issue_cmd(card, | 3741 | retval = cyz_issue_cmd(card, |
3743 | info->line - card->first_line, | 3742 | info->line - card->first_line, |
@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state) | |||
3758 | } | 3757 | } |
3759 | } | 3758 | } |
3760 | spin_unlock_irqrestore(&card->card_lock, flags); | 3759 | spin_unlock_irqrestore(&card->card_lock, flags); |
3760 | return retval; | ||
3761 | } /* cy_break */ | 3761 | } /* cy_break */ |
3762 | 3762 | ||
3763 | static int get_mon_info(struct cyclades_port *info, | 3763 | static int get_mon_info(struct cyclades_port *info, |
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index fada6ddefbae..c5e67a623951 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c | |||
@@ -20,10 +20,11 @@ | |||
20 | #include <linux/miscdevice.h> | 20 | #include <linux/miscdevice.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/bcd.h> | 22 | #include <linux/bcd.h> |
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/io.h> | ||
23 | 26 | ||
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/system.h> | 27 | #include <asm/system.h> |
26 | #include <asm/io.h> | ||
27 | #include <asm/rtc.h> | 28 | #include <asm/rtc.h> |
28 | #if defined(CONFIG_M32R) | 29 | #if defined(CONFIG_M32R) |
29 | #include <asm/m32r.h> | 30 | #include <asm/m32r.h> |
@@ -153,9 +154,7 @@ static unsigned char days_in_mo[] = | |||
153 | 154 | ||
154 | /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ | 155 | /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ |
155 | 156 | ||
156 | static int | 157 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
157 | rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
158 | unsigned long arg) | ||
159 | { | 158 | { |
160 | unsigned long flags; | 159 | unsigned long flags; |
161 | 160 | ||
@@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
165 | struct rtc_time rtc_tm; | 164 | struct rtc_time rtc_tm; |
166 | 165 | ||
167 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); | 166 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); |
167 | lock_kernel(); | ||
168 | get_rtc_time(&rtc_tm); | 168 | get_rtc_time(&rtc_tm); |
169 | unlock_kernel(); | ||
169 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) | 170 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) |
170 | return -EFAULT; | 171 | return -EFAULT; |
171 | return 0; | 172 | return 0; |
@@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
217 | BIN_TO_BCD(mon); | 218 | BIN_TO_BCD(mon); |
218 | BIN_TO_BCD(yrs); | 219 | BIN_TO_BCD(yrs); |
219 | 220 | ||
221 | lock_kernel(); | ||
220 | local_irq_save(flags); | 222 | local_irq_save(flags); |
221 | CMOS_WRITE(yrs, RTC_YEAR); | 223 | CMOS_WRITE(yrs, RTC_YEAR); |
222 | CMOS_WRITE(mon, RTC_MONTH); | 224 | CMOS_WRITE(mon, RTC_MONTH); |
@@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
225 | CMOS_WRITE(min, RTC_MINUTES); | 227 | CMOS_WRITE(min, RTC_MINUTES); |
226 | CMOS_WRITE(sec, RTC_SECONDS); | 228 | CMOS_WRITE(sec, RTC_SECONDS); |
227 | local_irq_restore(flags); | 229 | local_irq_restore(flags); |
230 | unlock_kernel(); | ||
228 | 231 | ||
229 | /* Notice that at this point, the RTC is updated but | 232 | /* Notice that at this point, the RTC is updated but |
230 | * the kernel is still running with the old time. | 233 | * the kernel is still running with the old time. |
@@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
244 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) | 247 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) |
245 | return -EFAULT; | 248 | return -EFAULT; |
246 | 249 | ||
250 | lock_kernel(); | ||
247 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); | 251 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); |
248 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); | 252 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); |
253 | unlock_kernel(); | ||
249 | return 0; | 254 | return 0; |
250 | } | 255 | } |
251 | default: | 256 | default: |
@@ -282,7 +287,7 @@ get_rtc_status(char *buf) | |||
282 | 287 | ||
283 | static const struct file_operations rtc_fops = { | 288 | static const struct file_operations rtc_fops = { |
284 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
285 | .ioctl = rtc_ioctl, | 290 | .unlocked_ioctl = rtc_ioctl, |
286 | }; | 291 | }; |
287 | 292 | ||
288 | /* Probe for the chip by writing something to its RAM and try reading it back. */ | 293 | /* Probe for the chip by writing something to its RAM and try reading it back. */ |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index b9a30c30e2b8..ca7c72a486b2 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
@@ -36,10 +36,10 @@ | |||
36 | #include <linux/smp_lock.h> | 36 | #include <linux/smp_lock.h> |
37 | #include <linux/firmware.h> | 37 | #include <linux/firmware.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/uaccess.h> /* For put_user and get_user */ | ||
39 | 40 | ||
40 | #include <asm/atarihw.h> | 41 | #include <asm/atarihw.h> |
41 | #include <asm/traps.h> | 42 | #include <asm/traps.h> |
42 | #include <asm/uaccess.h> /* For put_user and get_user */ | ||
43 | 43 | ||
44 | #include <asm/dsp56k.h> | 44 | #include <asm/dsp56k.h> |
45 | 45 | ||
@@ -303,10 +303,10 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co | |||
303 | } | 303 | } |
304 | } | 304 | } |
305 | 305 | ||
306 | static int dsp56k_ioctl(struct inode *inode, struct file *file, | 306 | static long dsp56k_ioctl(struct file *file, unsigned int cmd, |
307 | unsigned int cmd, unsigned long arg) | 307 | unsigned long arg) |
308 | { | 308 | { |
309 | int dev = iminor(inode) & 0x0f; | 309 | int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; |
310 | void __user *argp = (void __user *)arg; | 310 | void __user *argp = (void __user *)arg; |
311 | 311 | ||
312 | switch(dev) | 312 | switch(dev) |
@@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
331 | if (len > DSP56K_MAX_BINARY_LENGTH) { | 331 | if (len > DSP56K_MAX_BINARY_LENGTH) { |
332 | return -EINVAL; | 332 | return -EINVAL; |
333 | } | 333 | } |
334 | 334 | lock_kernel(); | |
335 | r = dsp56k_upload(bin, len); | 335 | r = dsp56k_upload(bin, len); |
336 | unlock_kernel(); | ||
336 | if (r < 0) { | 337 | if (r < 0) { |
337 | return r; | 338 | return r; |
338 | } | 339 | } |
@@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
342 | case DSP56K_SET_TX_WSIZE: | 343 | case DSP56K_SET_TX_WSIZE: |
343 | if (arg > 4 || arg < 1) | 344 | if (arg > 4 || arg < 1) |
344 | return -EINVAL; | 345 | return -EINVAL; |
346 | lock_kernel(); | ||
345 | dsp56k.tx_wsize = (int) arg; | 347 | dsp56k.tx_wsize = (int) arg; |
348 | unlock_kernel(); | ||
346 | break; | 349 | break; |
347 | case DSP56K_SET_RX_WSIZE: | 350 | case DSP56K_SET_RX_WSIZE: |
348 | if (arg > 4 || arg < 1) | 351 | if (arg > 4 || arg < 1) |
349 | return -EINVAL; | 352 | return -EINVAL; |
353 | lock_kernel(); | ||
350 | dsp56k.rx_wsize = (int) arg; | 354 | dsp56k.rx_wsize = (int) arg; |
355 | unlock_kernel(); | ||
351 | break; | 356 | break; |
352 | case DSP56K_HOST_FLAGS: | 357 | case DSP56K_HOST_FLAGS: |
353 | { | 358 | { |
@@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
359 | if(get_user(out, &hf->out) < 0) | 364 | if(get_user(out, &hf->out) < 0) |
360 | return -EFAULT; | 365 | return -EFAULT; |
361 | 366 | ||
367 | lock_kernel(); | ||
362 | if ((dir & 0x1) && (out & 0x1)) | 368 | if ((dir & 0x1) && (out & 0x1)) |
363 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; | 369 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; |
364 | else if (dir & 0x1) | 370 | else if (dir & 0x1) |
@@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
373 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; | 379 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; |
374 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; | 380 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; |
375 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; | 381 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; |
376 | 382 | unlock_kernel(); | |
377 | return put_user(status, &hf->status); | 383 | return put_user(status, &hf->status); |
378 | } | 384 | } |
379 | case DSP56K_HOST_CMD: | 385 | case DSP56K_HOST_CMD: |
380 | if (arg > 31 || arg < 0) | 386 | if (arg > 31 || arg < 0) |
381 | return -EINVAL; | 387 | return -EINVAL; |
388 | lock_kernel(); | ||
382 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | | 389 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | |
383 | DSP56K_CVR_HC); | 390 | DSP56K_CVR_HC); |
391 | unlock_kernel(); | ||
384 | break; | 392 | break; |
385 | default: | 393 | default: |
386 | return -EINVAL; | 394 | return -EINVAL; |
@@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = { | |||
472 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
473 | .read = dsp56k_read, | 481 | .read = dsp56k_read, |
474 | .write = dsp56k_write, | 482 | .write = dsp56k_write, |
475 | .ioctl = dsp56k_ioctl, | 483 | .unlocked_ioctl = dsp56k_ioctl, |
476 | .open = dsp56k_open, | 484 | .open = dsp56k_open, |
477 | .release = dsp56k_release, | 485 | .release = dsp56k_release, |
478 | }; | 486 | }; |
@@ -500,7 +508,8 @@ static int __init dsp56k_init_driver(void) | |||
500 | err = PTR_ERR(dsp56k_class); | 508 | err = PTR_ERR(dsp56k_class); |
501 | goto out_chrdev; | 509 | goto out_chrdev; |
502 | } | 510 | } |
503 | device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k"); | 511 | device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), |
512 | NULL, "dsp56k"); | ||
504 | 513 | ||
505 | printk(banner); | 514 | printk(banner); |
506 | goto out; | 515 | goto out; |
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index d57ca3e4e534..34d15d548236 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c | |||
@@ -37,8 +37,8 @@ | |||
37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
39 | #include <linux/efi.h> | 39 | #include <linux/efi.h> |
40 | #include <linux/uaccess.h> | ||
40 | 41 | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | 43 | ||
44 | #define EFI_RTC_VERSION "0.4" | 44 | #define EFI_RTC_VERSION "0.4" |
@@ -51,8 +51,8 @@ | |||
51 | 51 | ||
52 | static DEFINE_SPINLOCK(efi_rtc_lock); | 52 | static DEFINE_SPINLOCK(efi_rtc_lock); |
53 | 53 | ||
54 | static int efi_rtc_ioctl(struct inode *inode, struct file *file, | 54 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
55 | unsigned int cmd, unsigned long arg); | 55 | unsigned long arg); |
56 | 56 | ||
57 | #define is_leap(year) \ | 57 | #define is_leap(year) \ |
58 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | 58 | ((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) | |||
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
149 | static int | 149 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
150 | efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 150 | unsigned long arg) |
151 | unsigned long arg) | ||
152 | { | 151 | { |
153 | 152 | ||
154 | efi_status_t status; | 153 | efi_status_t status; |
@@ -175,13 +174,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
175 | return -EINVAL; | 174 | return -EINVAL; |
176 | 175 | ||
177 | case RTC_RD_TIME: | 176 | case RTC_RD_TIME: |
178 | 177 | lock_kernel(); | |
179 | spin_lock_irqsave(&efi_rtc_lock, flags); | 178 | spin_lock_irqsave(&efi_rtc_lock, flags); |
180 | 179 | ||
181 | status = efi.get_time(&eft, &cap); | 180 | status = efi.get_time(&eft, &cap); |
182 | 181 | ||
183 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 182 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
184 | 183 | unlock_kernel(); | |
185 | if (status != EFI_SUCCESS) { | 184 | if (status != EFI_SUCCESS) { |
186 | /* should never happen */ | 185 | /* should never happen */ |
187 | printk(KERN_ERR "efitime: can't read time\n"); | 186 | 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, | |||
203 | 202 | ||
204 | convert_to_efi_time(&wtime, &eft); | 203 | convert_to_efi_time(&wtime, &eft); |
205 | 204 | ||
205 | lock_kernel(); | ||
206 | spin_lock_irqsave(&efi_rtc_lock, flags); | 206 | spin_lock_irqsave(&efi_rtc_lock, flags); |
207 | 207 | ||
208 | status = efi.set_time(&eft); | 208 | status = efi.set_time(&eft); |
209 | 209 | ||
210 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 210 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
211 | unlock_kernel(); | ||
211 | 212 | ||
212 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 213 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
213 | 214 | ||
@@ -223,6 +224,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
223 | 224 | ||
224 | convert_to_efi_time(&wtime, &eft); | 225 | convert_to_efi_time(&wtime, &eft); |
225 | 226 | ||
227 | lock_kernel(); | ||
226 | spin_lock_irqsave(&efi_rtc_lock, flags); | 228 | spin_lock_irqsave(&efi_rtc_lock, flags); |
227 | /* | 229 | /* |
228 | * XXX Fixme: | 230 | * XXX Fixme: |
@@ -233,16 +235,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
233 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); | 235 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); |
234 | 236 | ||
235 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 237 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
238 | unlock_kernel(); | ||
236 | 239 | ||
237 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 240 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
238 | 241 | ||
239 | case RTC_WKALM_RD: | 242 | case RTC_WKALM_RD: |
240 | 243 | ||
244 | lock_kernel(); | ||
241 | spin_lock_irqsave(&efi_rtc_lock, flags); | 245 | spin_lock_irqsave(&efi_rtc_lock, flags); |
242 | 246 | ||
243 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); | 247 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); |
244 | 248 | ||
245 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 249 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
250 | unlock_kernel(); | ||
246 | 251 | ||
247 | if (status != EFI_SUCCESS) return -EINVAL; | 252 | if (status != EFI_SUCCESS) return -EINVAL; |
248 | 253 | ||
@@ -256,7 +261,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
256 | return copy_to_user(&ewp->time, &wtime, | 261 | return copy_to_user(&ewp->time, &wtime, |
257 | sizeof(struct rtc_time)) ? -EFAULT : 0; | 262 | sizeof(struct rtc_time)) ? -EFAULT : 0; |
258 | } | 263 | } |
259 | return -EINVAL; | 264 | return -ENOTTY; |
260 | } | 265 | } |
261 | 266 | ||
262 | /* | 267 | /* |
@@ -265,8 +270,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
265 | * up things on a close. | 270 | * up things on a close. |
266 | */ | 271 | */ |
267 | 272 | ||
268 | static int | 273 | static int efi_rtc_open(struct inode *inode, struct file *file) |
269 | efi_rtc_open(struct inode *inode, struct file *file) | ||
270 | { | 274 | { |
271 | /* | 275 | /* |
272 | * nothing special to do here | 276 | * nothing special to do here |
@@ -277,8 +281,7 @@ efi_rtc_open(struct inode *inode, struct file *file) | |||
277 | return 0; | 281 | return 0; |
278 | } | 282 | } |
279 | 283 | ||
280 | static int | 284 | static int efi_rtc_close(struct inode *inode, struct file *file) |
281 | efi_rtc_close(struct inode *inode, struct file *file) | ||
282 | { | 285 | { |
283 | return 0; | 286 | return 0; |
284 | } | 287 | } |
@@ -289,13 +292,12 @@ efi_rtc_close(struct inode *inode, struct file *file) | |||
289 | 292 | ||
290 | static const struct file_operations efi_rtc_fops = { | 293 | static const struct file_operations efi_rtc_fops = { |
291 | .owner = THIS_MODULE, | 294 | .owner = THIS_MODULE, |
292 | .ioctl = efi_rtc_ioctl, | 295 | .unlocked_ioctl = efi_rtc_ioctl, |
293 | .open = efi_rtc_open, | 296 | .open = efi_rtc_open, |
294 | .release = efi_rtc_close, | 297 | .release = efi_rtc_close, |
295 | }; | 298 | }; |
296 | 299 | ||
297 | static struct miscdevice efi_rtc_dev= | 300 | static struct miscdevice efi_rtc_dev= { |
298 | { | ||
299 | EFI_RTC_MINOR, | 301 | EFI_RTC_MINOR, |
300 | "efirtc", | 302 | "efirtc", |
301 | &efi_rtc_fops | 303 | &efi_rtc_fops |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index ac9995f6578b..456e4ede049f 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -184,9 +184,8 @@ static void pc_stop(struct tty_struct *); | |||
184 | static void pc_start(struct tty_struct *); | 184 | static void pc_start(struct tty_struct *); |
185 | static void pc_throttle(struct tty_struct *tty); | 185 | static void pc_throttle(struct tty_struct *tty); |
186 | static void pc_unthrottle(struct tty_struct *tty); | 186 | static void pc_unthrottle(struct tty_struct *tty); |
187 | static void digi_send_break(struct channel *ch, int msec); | 187 | static int pc_send_break(struct tty_struct *tty, int msec); |
188 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch); | 188 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch); |
189 | static void epca_setup(char *, int *); | ||
190 | 189 | ||
191 | static int pc_write(struct tty_struct *, const unsigned char *, int); | 190 | static int pc_write(struct tty_struct *, const unsigned char *, int); |
192 | static int pc_init(void); | 191 | static int pc_init(void); |
@@ -1040,6 +1039,7 @@ static const struct tty_operations pc_ops = { | |||
1040 | .throttle = pc_throttle, | 1039 | .throttle = pc_throttle, |
1041 | .unthrottle = pc_unthrottle, | 1040 | .unthrottle = pc_unthrottle, |
1042 | .hangup = pc_hangup, | 1041 | .hangup = pc_hangup, |
1042 | .break_ctl = pc_send_break | ||
1043 | }; | 1043 | }; |
1044 | 1044 | ||
1045 | static int info_open(struct tty_struct *tty, struct file *filp) | 1045 | static int info_open(struct tty_struct *tty, struct file *filp) |
@@ -1132,7 +1132,7 @@ static int __init pc_init(void) | |||
1132 | pc_driver->init_termios.c_lflag = 0; | 1132 | pc_driver->init_termios.c_lflag = 0; |
1133 | pc_driver->init_termios.c_ispeed = 9600; | 1133 | pc_driver->init_termios.c_ispeed = 9600; |
1134 | pc_driver->init_termios.c_ospeed = 9600; | 1134 | pc_driver->init_termios.c_ospeed = 9600; |
1135 | pc_driver->flags = TTY_DRIVER_REAL_RAW; | 1135 | pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; |
1136 | tty_set_operations(pc_driver, &pc_ops); | 1136 | tty_set_operations(pc_driver, &pc_ops); |
1137 | 1137 | ||
1138 | pc_info->owner = THIS_MODULE; | 1138 | pc_info->owner = THIS_MODULE; |
@@ -2177,7 +2177,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2177 | unsigned int cmd, unsigned long arg) | 2177 | unsigned int cmd, unsigned long arg) |
2178 | { | 2178 | { |
2179 | digiflow_t dflow; | 2179 | digiflow_t dflow; |
2180 | int retval; | ||
2181 | unsigned long flags; | 2180 | unsigned long flags; |
2182 | unsigned int mflag, mstat; | 2181 | unsigned int mflag, mstat; |
2183 | unsigned char startc, stopc; | 2182 | unsigned char startc, stopc; |
@@ -2189,37 +2188,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2189 | bc = ch->brdchan; | 2188 | bc = ch->brdchan; |
2190 | else | 2189 | else |
2191 | return -EINVAL; | 2190 | return -EINVAL; |
2192 | /* | ||
2193 | * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in | ||
2194 | * /usr/src/linux/drivers/char for a good example. In particular think | ||
2195 | * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS. | ||
2196 | */ | ||
2197 | switch (cmd) { | 2191 | switch (cmd) { |
2198 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
2199 | retval = tty_check_change(tty); | ||
2200 | if (retval) | ||
2201 | return retval; | ||
2202 | /* Setup an event to indicate when the transmit | ||
2203 | buffer empties */ | ||
2204 | spin_lock_irqsave(&epca_lock, flags); | ||
2205 | setup_empty_event(tty, ch); | ||
2206 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2207 | tty_wait_until_sent(tty, 0); | ||
2208 | if (!arg) | ||
2209 | digi_send_break(ch, HZ / 4); /* 1/4 second */ | ||
2210 | return 0; | ||
2211 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
2212 | retval = tty_check_change(tty); | ||
2213 | if (retval) | ||
2214 | return retval; | ||
2215 | /* Setup an event to indicate when the transmit buffer | ||
2216 | empties */ | ||
2217 | spin_lock_irqsave(&epca_lock, flags); | ||
2218 | setup_empty_event(tty, ch); | ||
2219 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2220 | tty_wait_until_sent(tty, 0); | ||
2221 | digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); | ||
2222 | return 0; | ||
2223 | case TIOCMODG: | 2192 | case TIOCMODG: |
2224 | mflag = pc_tiocmget(tty, file); | 2193 | mflag = pc_tiocmget(tty, file); |
2225 | if (put_user(mflag, (unsigned long __user *)argp)) | 2194 | if (put_user(mflag, (unsigned long __user *)argp)) |
@@ -2505,10 +2474,14 @@ static void pc_unthrottle(struct tty_struct *tty) | |||
2505 | } | 2474 | } |
2506 | } | 2475 | } |
2507 | 2476 | ||
2508 | static void digi_send_break(struct channel *ch, int msec) | 2477 | static int pc_send_break(struct tty_struct *tty, int msec) |
2509 | { | 2478 | { |
2479 | struct channel *ch = (struct channel *) tty->driver_data; | ||
2510 | unsigned long flags; | 2480 | unsigned long flags; |
2511 | 2481 | ||
2482 | if (msec == -1) | ||
2483 | return -EOPNOTSUPP; | ||
2484 | |||
2512 | spin_lock_irqsave(&epca_lock, flags); | 2485 | spin_lock_irqsave(&epca_lock, flags); |
2513 | globalwinon(ch); | 2486 | globalwinon(ch); |
2514 | /* | 2487 | /* |
@@ -2521,6 +2494,7 @@ static void digi_send_break(struct channel *ch, int msec) | |||
2521 | fepcmd(ch, SENDBREAK, msec, 0, 10, 0); | 2494 | fepcmd(ch, SENDBREAK, msec, 0, 10, 0); |
2522 | memoff(ch); | 2495 | memoff(ch); |
2523 | spin_unlock_irqrestore(&epca_lock, flags); | 2496 | spin_unlock_irqrestore(&epca_lock, flags); |
2497 | return 0; | ||
2524 | } | 2498 | } |
2525 | 2499 | ||
2526 | /* Caller MUST hold the lock */ | 2500 | /* Caller MUST hold the lock */ |
@@ -2538,7 +2512,8 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch) | |||
2538 | memoff(ch); | 2512 | memoff(ch); |
2539 | } | 2513 | } |
2540 | 2514 | ||
2541 | static void epca_setup(char *str, int *ints) | 2515 | #ifndef MODULE |
2516 | static void __init epca_setup(char *str, int *ints) | ||
2542 | { | 2517 | { |
2543 | struct board_info board; | 2518 | struct board_info board; |
2544 | int index, loop, last; | 2519 | int index, loop, last; |
@@ -2792,6 +2767,17 @@ static void epca_setup(char *str, int *ints) | |||
2792 | num_cards++; | 2767 | num_cards++; |
2793 | } | 2768 | } |
2794 | 2769 | ||
2770 | static int __init epca_real_setup(char *str) | ||
2771 | { | ||
2772 | int ints[11]; | ||
2773 | |||
2774 | epca_setup(get_options(str, 11, ints), ints); | ||
2775 | return 1; | ||
2776 | } | ||
2777 | |||
2778 | __setup("digiepca", epca_real_setup); | ||
2779 | #endif | ||
2780 | |||
2795 | enum epic_board_types { | 2781 | enum epic_board_types { |
2796 | brd_xr = 0, | 2782 | brd_xr = 0, |
2797 | brd_xem, | 2783 | brd_xem, |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 2eaf09f93e3d..7f077c0097f6 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file, | |||
1725 | /* | 1725 | /* |
1726 | * rs_break() --- routine which turns the break handling on or off | 1726 | * rs_break() --- routine which turns the break handling on or off |
1727 | */ | 1727 | */ |
1728 | static void esp_break(struct tty_struct *tty, int break_state) | 1728 | static int esp_break(struct tty_struct *tty, int break_state) |
1729 | { | 1729 | { |
1730 | struct esp_struct *info = tty->driver_data; | 1730 | struct esp_struct *info = tty->driver_data; |
1731 | unsigned long flags; | 1731 | unsigned long flags; |
1732 | 1732 | ||
1733 | if (serial_paranoia_check(info, tty->name, "esp_break")) | 1733 | if (serial_paranoia_check(info, tty->name, "esp_break")) |
1734 | return; | 1734 | return -EINVAL; |
1735 | 1735 | ||
1736 | if (break_state == -1) { | 1736 | if (break_state == -1) { |
1737 | spin_lock_irqsave(&info->lock, flags); | 1737 | spin_lock_irqsave(&info->lock, flags); |
@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state) | |||
1747 | serial_out(info, UART_ESI_CMD2, 0x00); | 1747 | serial_out(info, UART_ESI_CMD2, 0x00); |
1748 | spin_unlock_irqrestore(&info->lock, flags); | 1748 | spin_unlock_irqrestore(&info->lock, flags); |
1749 | } | 1749 | } |
1750 | return 0; | ||
1750 | } | 1751 | } |
1751 | 1752 | ||
1752 | static int rs_ioctl(struct tty_struct *tty, struct file *file, | 1753 | static int rs_ioctl(struct tty_struct *tty, struct file *file, |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fb0a85a1eb36..b3f5dbc6d880 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp) | |||
623 | return -ENXIO; | 623 | return -ENXIO; |
624 | } | 624 | } |
625 | 625 | ||
626 | #if 0 | ||
626 | int hpet_unregister(struct hpet_task *tp) | 627 | int hpet_unregister(struct hpet_task *tp) |
627 | { | 628 | { |
628 | struct hpet_dev *devp; | 629 | struct hpet_dev *devp; |
@@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp) | |||
652 | 653 | ||
653 | return 0; | 654 | return 0; |
654 | } | 655 | } |
656 | #endif /* 0 */ | ||
655 | 657 | ||
656 | static ctl_table hpet_table[] = { | 658 | static ctl_table hpet_table[] = { |
657 | { | 659 | { |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d625cc..02aac104842d 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/kbd_kern.h> | 28 | #include <linux/kbd_kern.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/kref.h> | ||
31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
32 | #include <linux/list.h> | 31 | #include <linux/list.h> |
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
@@ -75,23 +74,6 @@ static int hvc_init(void); | |||
75 | static int sysrq_pressed; | 74 | static int sysrq_pressed; |
76 | #endif | 75 | #endif |
77 | 76 | ||
78 | struct hvc_struct { | ||
79 | spinlock_t lock; | ||
80 | int index; | ||
81 | struct tty_struct *tty; | ||
82 | unsigned int count; | ||
83 | int do_wakeup; | ||
84 | char *outbuf; | ||
85 | int outbuf_size; | ||
86 | int n_outbuf; | ||
87 | uint32_t vtermno; | ||
88 | struct hv_ops *ops; | ||
89 | int irq_requested; | ||
90 | int irq; | ||
91 | struct list_head next; | ||
92 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
93 | }; | ||
94 | |||
95 | /* dynamic list of hvc_struct instances */ | 77 | /* dynamic list of hvc_struct instances */ |
96 | static LIST_HEAD(hvc_structs); | 78 | static LIST_HEAD(hvc_structs); |
97 | 79 | ||
@@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
298 | 280 | ||
299 | return 0; | 281 | return 0; |
300 | } | 282 | } |
283 | EXPORT_SYMBOL_GPL(hvc_instantiate); | ||
301 | 284 | ||
302 | /* Wake the sleeping khvcd */ | 285 | /* Wake the sleeping khvcd */ |
303 | static void hvc_kick(void) | 286 | void hvc_kick(void) |
304 | { | 287 | { |
305 | hvc_kicked = 1; | 288 | hvc_kicked = 1; |
306 | wake_up_process(hvc_task); | 289 | wake_up_process(hvc_task); |
307 | } | 290 | } |
308 | 291 | EXPORT_SYMBOL_GPL(hvc_kick); | |
309 | static int hvc_poll(struct hvc_struct *hp); | ||
310 | |||
311 | /* | ||
312 | * NOTE: This API isn't used if the console adapter doesn't support interrupts. | ||
313 | * In this case the console is poll driven. | ||
314 | */ | ||
315 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
316 | { | ||
317 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
318 | if (hvc_poll(dev_instance)) | ||
319 | hvc_kick(); | ||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | 292 | ||
323 | static void hvc_unthrottle(struct tty_struct *tty) | 293 | static void hvc_unthrottle(struct tty_struct *tty) |
324 | { | 294 | { |
@@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
333 | { | 303 | { |
334 | struct hvc_struct *hp; | 304 | struct hvc_struct *hp; |
335 | unsigned long flags; | 305 | unsigned long flags; |
336 | int irq = 0; | ||
337 | int rc = 0; | 306 | int rc = 0; |
338 | 307 | ||
339 | /* Auto increments kref reference if found. */ | 308 | /* Auto increments kref reference if found. */ |
@@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
352 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ | 321 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ |
353 | 322 | ||
354 | hp->tty = tty; | 323 | hp->tty = tty; |
355 | /* Save for request_irq outside of spin_lock. */ | 324 | |
356 | irq = hp->irq; | 325 | if (hp->ops->notifier_add) |
357 | if (irq) | 326 | rc = hp->ops->notifier_add(hp, hp->data); |
358 | hp->irq_requested = 1; | ||
359 | 327 | ||
360 | spin_unlock_irqrestore(&hp->lock, flags); | 328 | spin_unlock_irqrestore(&hp->lock, flags); |
361 | /* check error, fallback to non-irq */ | 329 | |
362 | if (irq) | ||
363 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); | ||
364 | 330 | ||
365 | /* | 331 | /* |
366 | * If the request_irq() fails and we return an error. The tty layer | 332 | * If the notifier fails we return an error. The tty layer |
367 | * will call hvc_close() after a failed open but we don't want to clean | 333 | * will call hvc_close() after a failed open but we don't want to clean |
368 | * up there so we'll clean up here and clear out the previously set | 334 | * up there so we'll clean up here and clear out the previously set |
369 | * tty fields and return the kref reference. | 335 | * tty fields and return the kref reference. |
@@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
371 | if (rc) { | 337 | if (rc) { |
372 | spin_lock_irqsave(&hp->lock, flags); | 338 | spin_lock_irqsave(&hp->lock, flags); |
373 | hp->tty = NULL; | 339 | hp->tty = NULL; |
374 | hp->irq_requested = 0; | ||
375 | spin_unlock_irqrestore(&hp->lock, flags); | 340 | spin_unlock_irqrestore(&hp->lock, flags); |
376 | tty->driver_data = NULL; | 341 | tty->driver_data = NULL; |
377 | kref_put(&hp->kref, destroy_hvc_struct); | 342 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
386 | static void hvc_close(struct tty_struct *tty, struct file * filp) | 351 | static void hvc_close(struct tty_struct *tty, struct file * filp) |
387 | { | 352 | { |
388 | struct hvc_struct *hp; | 353 | struct hvc_struct *hp; |
389 | int irq = 0; | ||
390 | unsigned long flags; | 354 | unsigned long flags; |
391 | 355 | ||
392 | if (tty_hung_up_p(filp)) | 356 | if (tty_hung_up_p(filp)) |
@@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
404 | spin_lock_irqsave(&hp->lock, flags); | 368 | spin_lock_irqsave(&hp->lock, flags); |
405 | 369 | ||
406 | if (--hp->count == 0) { | 370 | if (--hp->count == 0) { |
407 | if (hp->irq_requested) | 371 | if (hp->ops->notifier_del) |
408 | irq = hp->irq; | 372 | hp->ops->notifier_del(hp, hp->data); |
409 | hp->irq_requested = 0; | ||
410 | 373 | ||
411 | /* We are done with the tty pointer now. */ | 374 | /* We are done with the tty pointer now. */ |
412 | hp->tty = NULL; | 375 | hp->tty = NULL; |
@@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
418 | * waking periodically to check chars_in_buffer(). | 381 | * waking periodically to check chars_in_buffer(). |
419 | */ | 382 | */ |
420 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | 383 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); |
421 | |||
422 | if (irq) | ||
423 | free_irq(irq, hp); | ||
424 | |||
425 | } else { | 384 | } else { |
426 | if (hp->count < 0) | 385 | if (hp->count < 0) |
427 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", | 386 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
@@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty) | |||
436 | { | 395 | { |
437 | struct hvc_struct *hp = tty->driver_data; | 396 | struct hvc_struct *hp = tty->driver_data; |
438 | unsigned long flags; | 397 | unsigned long flags; |
439 | int irq = 0; | ||
440 | int temp_open_count; | 398 | int temp_open_count; |
441 | 399 | ||
442 | if (!hp) | 400 | if (!hp) |
@@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty) | |||
458 | hp->count = 0; | 416 | hp->count = 0; |
459 | hp->n_outbuf = 0; | 417 | hp->n_outbuf = 0; |
460 | hp->tty = NULL; | 418 | hp->tty = NULL; |
461 | if (hp->irq_requested) | 419 | |
462 | /* Saved for use outside of spin_lock. */ | 420 | if (hp->ops->notifier_del) |
463 | irq = hp->irq; | 421 | hp->ops->notifier_del(hp, hp->data); |
464 | hp->irq_requested = 0; | 422 | |
465 | spin_unlock_irqrestore(&hp->lock, flags); | 423 | spin_unlock_irqrestore(&hp->lock, flags); |
466 | if (irq) | 424 | |
467 | free_irq(irq, hp); | ||
468 | while(temp_open_count) { | 425 | while(temp_open_count) { |
469 | --temp_open_count; | 426 | --temp_open_count; |
470 | kref_put(&hp->kref, destroy_hvc_struct); | 427 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT; | |||
575 | #define HVC_POLL_READ 0x00000001 | 532 | #define HVC_POLL_READ 0x00000001 |
576 | #define HVC_POLL_WRITE 0x00000002 | 533 | #define HVC_POLL_WRITE 0x00000002 |
577 | 534 | ||
578 | static int hvc_poll(struct hvc_struct *hp) | 535 | int hvc_poll(struct hvc_struct *hp) |
579 | { | 536 | { |
580 | struct tty_struct *tty; | 537 | struct tty_struct *tty; |
581 | int i, n, poll_mask = 0; | 538 | int i, n, poll_mask = 0; |
@@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp) | |||
602 | if (test_bit(TTY_THROTTLED, &tty->flags)) | 559 | if (test_bit(TTY_THROTTLED, &tty->flags)) |
603 | goto throttled; | 560 | goto throttled; |
604 | 561 | ||
605 | /* If we aren't interrupt driven and aren't throttled, we always | 562 | /* If we aren't notifier driven and aren't throttled, we always |
606 | * request a reschedule | 563 | * request a reschedule |
607 | */ | 564 | */ |
608 | if (hp->irq == 0) | 565 | if (!hp->irq_requested) |
609 | poll_mask |= HVC_POLL_READ; | 566 | poll_mask |= HVC_POLL_READ; |
610 | 567 | ||
611 | /* Read data if any */ | 568 | /* Read data if any */ |
@@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp) | |||
674 | 631 | ||
675 | return poll_mask; | 632 | return poll_mask; |
676 | } | 633 | } |
634 | EXPORT_SYMBOL_GPL(hvc_poll); | ||
677 | 635 | ||
678 | /* | 636 | /* |
679 | * This kthread is either polling or interrupt driven. This is determined by | 637 | * This kthread is either polling or interrupt driven. This is determined by |
@@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = { | |||
733 | .chars_in_buffer = hvc_chars_in_buffer, | 691 | .chars_in_buffer = hvc_chars_in_buffer, |
734 | }; | 692 | }; |
735 | 693 | ||
736 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | 694 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, |
737 | struct hv_ops *ops, int outbuf_size) | 695 | struct hv_ops *ops, int outbuf_size) |
738 | { | 696 | { |
739 | struct hvc_struct *hp; | 697 | struct hvc_struct *hp; |
@@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
754 | memset(hp, 0x00, sizeof(*hp)); | 712 | memset(hp, 0x00, sizeof(*hp)); |
755 | 713 | ||
756 | hp->vtermno = vtermno; | 714 | hp->vtermno = vtermno; |
757 | hp->irq = irq; | 715 | hp->data = data; |
758 | hp->ops = ops; | 716 | hp->ops = ops; |
759 | hp->outbuf_size = outbuf_size; | 717 | hp->outbuf_size = outbuf_size; |
760 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; | 718 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; |
@@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
784 | 742 | ||
785 | return hp; | 743 | return hp; |
786 | } | 744 | } |
745 | EXPORT_SYMBOL_GPL(hvc_alloc); | ||
787 | 746 | ||
788 | int __devexit hvc_remove(struct hvc_struct *hp) | 747 | int __devexit hvc_remove(struct hvc_struct *hp) |
789 | { | 748 | { |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 42ffb17e15df..9790201718ae 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Ryan S. Arnold <rsa@us.ibm.com> | 6 | * Ryan S. Arnold <rsa@us.ibm.com> |
7 | * | 7 | * |
8 | * hvc_console header information: | 8 | * hvc_console header information: |
9 | * moved here from include/asm-powerpc/hvconsole.h | 9 | * moved here from arch/powerpc/include/asm/hvconsole.h |
10 | * and drivers/char/hvc_console.c | 10 | * and drivers/char/hvc_console.c |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #ifndef HVC_CONSOLE_H | 27 | #ifndef HVC_CONSOLE_H |
28 | #define HVC_CONSOLE_H | 28 | #define HVC_CONSOLE_H |
29 | #include <linux/kref.h> | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * This is the max number of console adapters that can/will be found as | 32 | * This is the max number of console adapters that can/will be found as |
@@ -42,24 +43,50 @@ | |||
42 | */ | 43 | */ |
43 | #define HVC_ALLOC_TTY_ADAPTERS 8 | 44 | #define HVC_ALLOC_TTY_ADAPTERS 8 |
44 | 45 | ||
46 | struct hvc_struct { | ||
47 | spinlock_t lock; | ||
48 | int index; | ||
49 | struct tty_struct *tty; | ||
50 | unsigned int count; | ||
51 | int do_wakeup; | ||
52 | char *outbuf; | ||
53 | int outbuf_size; | ||
54 | int n_outbuf; | ||
55 | uint32_t vtermno; | ||
56 | struct hv_ops *ops; | ||
57 | int irq_requested; | ||
58 | int data; | ||
59 | struct list_head next; | ||
60 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
61 | }; | ||
45 | 62 | ||
46 | /* implemented by a low level driver */ | 63 | /* implemented by a low level driver */ |
47 | struct hv_ops { | 64 | struct hv_ops { |
48 | int (*get_chars)(uint32_t vtermno, char *buf, int count); | 65 | int (*get_chars)(uint32_t vtermno, char *buf, int count); |
49 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); | 66 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); |
50 | }; | ||
51 | 67 | ||
52 | struct hvc_struct; | 68 | /* Callbacks for notification. Called in open and close */ |
69 | int (*notifier_add)(struct hvc_struct *hp, int irq); | ||
70 | void (*notifier_del)(struct hvc_struct *hp, int irq); | ||
71 | }; | ||
53 | 72 | ||
54 | /* Register a vterm and a slot index for use as a console (console_init) */ | 73 | /* Register a vterm and a slot index for use as a console (console_init) */ |
55 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); | 74 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); |
56 | 75 | ||
57 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ | 76 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ |
58 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, | 77 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, |
59 | struct hv_ops *ops, int outbuf_size); | 78 | struct hv_ops *ops, int outbuf_size); |
60 | /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ | 79 | /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ |
61 | extern int __devexit hvc_remove(struct hvc_struct *hp); | 80 | extern int __devexit hvc_remove(struct hvc_struct *hp); |
62 | 81 | ||
82 | /* data available */ | ||
83 | int hvc_poll(struct hvc_struct *hp); | ||
84 | void hvc_kick(void); | ||
85 | |||
86 | /* default notifier for irq based notification */ | ||
87 | extern int notifier_add_irq(struct hvc_struct *hp, int data); | ||
88 | extern void notifier_del_irq(struct hvc_struct *hp, int data); | ||
89 | |||
63 | 90 | ||
64 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) | 91 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) |
65 | #include <asm/xmon.h> | 92 | #include <asm/xmon.h> |
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c new file mode 100644 index 000000000000..73a59cdb8947 --- /dev/null +++ b/drivers/char/hvc_irq.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2001,2008 | ||
3 | * | ||
4 | * This file contains the IRQ specific code for hvc_console | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/interrupt.h> | ||
9 | |||
10 | #include "hvc_console.h" | ||
11 | |||
12 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
13 | { | ||
14 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
15 | if (hvc_poll(dev_instance)) | ||
16 | hvc_kick(); | ||
17 | return IRQ_HANDLED; | ||
18 | } | ||
19 | |||
20 | /* | ||
21 | * For IRQ based systems these callbacks can be used | ||
22 | */ | ||
23 | int notifier_add_irq(struct hvc_struct *hp, int irq) | ||
24 | { | ||
25 | int rc; | ||
26 | |||
27 | if (!irq) { | ||
28 | hp->irq_requested = 0; | ||
29 | return 0; | ||
30 | } | ||
31 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, | ||
32 | "hvc_console", hp); | ||
33 | if (!rc) | ||
34 | hp->irq_requested = 1; | ||
35 | return rc; | ||
36 | } | ||
37 | |||
38 | void notifier_del_irq(struct hvc_struct *hp, int irq) | ||
39 | { | ||
40 | if (!irq) | ||
41 | return; | ||
42 | free_irq(irq, hp); | ||
43 | hp->irq_requested = 0; | ||
44 | } | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index a08f8f981c11..b71c610fe5ae 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -200,6 +200,8 @@ done: | |||
200 | static struct hv_ops hvc_get_put_ops = { | 200 | static struct hv_ops hvc_get_put_ops = { |
201 | .get_chars = get_chars, | 201 | .get_chars = get_chars, |
202 | .put_chars = put_chars, | 202 | .put_chars = put_chars, |
203 | .notifier_add = notifier_add_irq, | ||
204 | .notifier_del = notifier_del_irq, | ||
203 | }; | 205 | }; |
204 | 206 | ||
205 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 207 | 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 79711aa4b41d..93f3840c1682 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) | |||
80 | static struct hv_ops hvc_get_put_ops = { | 80 | static struct hv_ops hvc_get_put_ops = { |
81 | .get_chars = filtered_get_chars, | 81 | .get_chars = filtered_get_chars, |
82 | .put_chars = hvc_put_chars, | 82 | .put_chars = hvc_put_chars, |
83 | .notifier_add = notifier_add_irq, | ||
84 | .notifier_del = notifier_del_irq, | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 87 | 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 db2ae4216279..6b70aa66a587 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) | |||
100 | static struct hv_ops hvc_ops = { | 100 | static struct hv_ops hvc_ops = { |
101 | .get_chars = read_console, | 101 | .get_chars = read_console, |
102 | .put_chars = write_console, | 102 | .put_chars = write_console, |
103 | .notifier_add = notifier_add_irq, | ||
104 | .notifier_del = notifier_del_irq, | ||
103 | }; | 105 | }; |
104 | 106 | ||
105 | static int __init xen_init(void) | 107 | static int __init xen_init(void) |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 786d518e9477..473d9b14439a 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -114,7 +114,7 @@ | |||
114 | * the hvcs_final_close() function in order to get it out of the spinlock. | 114 | * the hvcs_final_close() function in order to get it out of the spinlock. |
115 | * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping | 115 | * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping |
116 | * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from | 116 | * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from |
117 | * include/asm-powerpc/hvcserver.h | 117 | * arch/powerepc/include/asm/hvcserver.h |
118 | * | 118 | * |
119 | * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to | 119 | * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to |
120 | * prevent possible lockup with realtime scheduling as similarily pointed out by | 120 | * prevent possible lockup with realtime scheduling as similarily pointed out by |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index efd0b4db7c8e..8822eca58ffa 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -59,6 +59,19 @@ config HW_RANDOM_GEODE | |||
59 | 59 | ||
60 | If unsure, say Y. | 60 | If unsure, say Y. |
61 | 61 | ||
62 | config HW_RANDOM_N2RNG | ||
63 | tristate "Niagara2 Random Number Generator support" | ||
64 | depends on HW_RANDOM && SPARC64 | ||
65 | default HW_RANDOM | ||
66 | ---help--- | ||
67 | This driver provides kernel-side support for the Random Number | ||
68 | Generator hardware found on Niagara2 cpus. | ||
69 | |||
70 | To compile this driver as a module, choose M here: the | ||
71 | module will be called n2-rng. | ||
72 | |||
73 | If unsure, say Y. | ||
74 | |||
62 | config HW_RANDOM_VIA | 75 | config HW_RANDOM_VIA |
63 | tristate "VIA HW Random Number Generator support" | 76 | tristate "VIA HW Random Number Generator support" |
64 | depends on HW_RANDOM && X86_32 | 77 | depends on HW_RANDOM && X86_32 |
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b4940ddbb35f..b6effb7522c2 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -7,6 +7,8 @@ rng-core-y := core.o | |||
7 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o | 7 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o |
8 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o | 8 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o |
9 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o | 9 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o |
10 | obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o | ||
11 | n2-rng-y := n2-drv.o n2-asm.o | ||
10 | obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o | 12 | obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o |
11 | obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o | 13 | obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o |
12 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o | 14 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o |
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 27fdc0866496..8a2fce0756ec 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) | |||
241 | struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; | 241 | struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; |
242 | u8 mfc, dvc; | 242 | u8 mfc, dvc; |
243 | 243 | ||
244 | /* interrupts disabled in stop_machine_run call */ | 244 | /* interrupts disabled in stop_machine call */ |
245 | 245 | ||
246 | if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) | 246 | if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) |
247 | pci_write_config_byte(intel_rng_hw->dev, | 247 | pci_write_config_byte(intel_rng_hw->dev, |
@@ -365,10 +365,10 @@ static int __init mod_init(void) | |||
365 | * location with the Read ID command, all activity on the system | 365 | * location with the Read ID command, all activity on the system |
366 | * must be stopped until the state is back to normal. | 366 | * must be stopped until the state is back to normal. |
367 | * | 367 | * |
368 | * Use stop_machine_run because IPIs can be blocked by disabling | 368 | * Use stop_machine because IPIs can be blocked by disabling |
369 | * interrupts. | 369 | * interrupts. |
370 | */ | 370 | */ |
371 | err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS); | 371 | err = stop_machine(intel_rng_hw_init, intel_rng_hw, NULL); |
372 | pci_dev_put(dev); | 372 | pci_dev_put(dev); |
373 | iounmap(intel_rng_hw->mem); | 373 | iounmap(intel_rng_hw->mem); |
374 | kfree(intel_rng_hw); | 374 | kfree(intel_rng_hw); |
diff --git a/drivers/char/hw_random/n2-asm.S b/drivers/char/hw_random/n2-asm.S new file mode 100644 index 000000000000..9b6eb5cd59f6 --- /dev/null +++ b/drivers/char/hw_random/n2-asm.S | |||
@@ -0,0 +1,79 @@ | |||
1 | /* n2-asm.S: Niagara2 RNG hypervisor call assembler. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | #include <linux/linkage.h> | ||
6 | #include <asm/hypervisor.h> | ||
7 | #include "n2rng.h" | ||
8 | |||
9 | .text | ||
10 | |||
11 | ENTRY(sun4v_rng_get_diag_ctl) | ||
12 | mov HV_FAST_RNG_GET_DIAG_CTL, %o5 | ||
13 | ta HV_FAST_TRAP | ||
14 | retl | ||
15 | nop | ||
16 | ENDPROC(sun4v_rng_get_diag_ctl) | ||
17 | |||
18 | ENTRY(sun4v_rng_ctl_read_v1) | ||
19 | mov %o1, %o3 | ||
20 | mov %o2, %o4 | ||
21 | mov HV_FAST_RNG_CTL_READ, %o5 | ||
22 | ta HV_FAST_TRAP | ||
23 | stx %o1, [%o3] | ||
24 | retl | ||
25 | stx %o2, [%o4] | ||
26 | ENDPROC(sun4v_rng_ctl_read_v1) | ||
27 | |||
28 | ENTRY(sun4v_rng_ctl_read_v2) | ||
29 | save %sp, -192, %sp | ||
30 | mov %i0, %o0 | ||
31 | mov %i1, %o1 | ||
32 | mov HV_FAST_RNG_CTL_READ, %o5 | ||
33 | ta HV_FAST_TRAP | ||
34 | stx %o1, [%i2] | ||
35 | stx %o2, [%i3] | ||
36 | stx %o3, [%i4] | ||
37 | stx %o4, [%i5] | ||
38 | ret | ||
39 | restore %g0, %o0, %o0 | ||
40 | ENDPROC(sun4v_rng_ctl_read_v2) | ||
41 | |||
42 | ENTRY(sun4v_rng_ctl_write_v1) | ||
43 | mov %o3, %o4 | ||
44 | mov HV_FAST_RNG_CTL_WRITE, %o5 | ||
45 | ta HV_FAST_TRAP | ||
46 | retl | ||
47 | stx %o1, [%o4] | ||
48 | ENDPROC(sun4v_rng_ctl_write_v1) | ||
49 | |||
50 | ENTRY(sun4v_rng_ctl_write_v2) | ||
51 | mov HV_FAST_RNG_CTL_WRITE, %o5 | ||
52 | ta HV_FAST_TRAP | ||
53 | retl | ||
54 | nop | ||
55 | ENDPROC(sun4v_rng_ctl_write_v2) | ||
56 | |||
57 | ENTRY(sun4v_rng_data_read_diag_v1) | ||
58 | mov %o2, %o4 | ||
59 | mov HV_FAST_RNG_DATA_READ_DIAG, %o5 | ||
60 | ta HV_FAST_TRAP | ||
61 | retl | ||
62 | stx %o1, [%o4] | ||
63 | ENDPROC(sun4v_rng_data_read_diag_v1) | ||
64 | |||
65 | ENTRY(sun4v_rng_data_read_diag_v2) | ||
66 | mov %o3, %o4 | ||
67 | mov HV_FAST_RNG_DATA_READ_DIAG, %o5 | ||
68 | ta HV_FAST_TRAP | ||
69 | retl | ||
70 | stx %o1, [%o4] | ||
71 | ENDPROC(sun4v_rng_data_read_diag_v2) | ||
72 | |||
73 | ENTRY(sun4v_rng_data_read) | ||
74 | mov %o1, %o4 | ||
75 | mov HV_FAST_RNG_DATA_READ, %o5 | ||
76 | ta HV_FAST_TRAP | ||
77 | retl | ||
78 | stx %o1, [%o4] | ||
79 | ENDPROC(sun4v_rng_data_read) | ||
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c new file mode 100644 index 000000000000..5220f541df25 --- /dev/null +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -0,0 +1,771 @@ | |||
1 | /* n2-drv.c: Niagara-2 RNG driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/workqueue.h> | ||
13 | #include <linux/preempt.h> | ||
14 | #include <linux/hw_random.h> | ||
15 | |||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_device.h> | ||
18 | |||
19 | #include <asm/hypervisor.h> | ||
20 | |||
21 | #include "n2rng.h" | ||
22 | |||
23 | #define DRV_MODULE_NAME "n2rng" | ||
24 | #define PFX DRV_MODULE_NAME ": " | ||
25 | #define DRV_MODULE_VERSION "0.1" | ||
26 | #define DRV_MODULE_RELDATE "May 15, 2008" | ||
27 | |||
28 | static char version[] __devinitdata = | ||
29 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | ||
30 | |||
31 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
32 | MODULE_DESCRIPTION("Niagara2 RNG driver"); | ||
33 | MODULE_LICENSE("GPL"); | ||
34 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
35 | |||
36 | /* The Niagara2 RNG provides a 64-bit read-only random number | ||
37 | * register, plus a control register. Access to the RNG is | ||
38 | * virtualized through the hypervisor so that both guests and control | ||
39 | * nodes can access the device. | ||
40 | * | ||
41 | * The entropy source consists of raw entropy sources, each | ||
42 | * constructed from a voltage controlled oscillator whose phase is | ||
43 | * jittered by thermal noise sources. | ||
44 | * | ||
45 | * The oscillator in each of the three raw entropy sources run at | ||
46 | * different frequencies. Normally, all three generator outputs are | ||
47 | * gathered, xored together, and fed into a CRC circuit, the output of | ||
48 | * which is the 64-bit read-only register. | ||
49 | * | ||
50 | * Some time is necessary for all the necessary entropy to build up | ||
51 | * such that a full 64-bits of entropy are available in the register. | ||
52 | * In normal operating mode (RNG_CTL_LFSR is set), the chip implements | ||
53 | * an interlock which blocks register reads until sufficient entropy | ||
54 | * is available. | ||
55 | * | ||
56 | * A control register is provided for adjusting various aspects of RNG | ||
57 | * operation, and to enable diagnostic modes. Each of the three raw | ||
58 | * entropy sources has an enable bit (RNG_CTL_ES{1,2,3}). Also | ||
59 | * provided are fields for controlling the minimum time in cycles | ||
60 | * between read accesses to the register (RNG_CTL_WAIT, this controls | ||
61 | * the interlock described in the previous paragraph). | ||
62 | * | ||
63 | * The standard setting is to have the mode bit (RNG_CTL_LFSR) set, | ||
64 | * all three entropy sources enabled, and the interlock time set | ||
65 | * appropriately. | ||
66 | * | ||
67 | * The CRC polynomial used by the chip is: | ||
68 | * | ||
69 | * P(X) = x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + x46 + | ||
70 | * x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + x28 + x25 + | ||
71 | * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 | ||
72 | * | ||
73 | * The RNG_CTL_VCO value of each noise cell must be programmed | ||
74 | * seperately. This is why 4 control register values must be provided | ||
75 | * to the hypervisor. During a write, the hypervisor writes them all, | ||
76 | * one at a time, to the actual RNG_CTL register. The first three | ||
77 | * values are used to setup the desired RNG_CTL_VCO for each entropy | ||
78 | * source, for example: | ||
79 | * | ||
80 | * control 0: (1 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES1 | ||
81 | * control 1: (2 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES2 | ||
82 | * control 2: (3 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES3 | ||
83 | * | ||
84 | * And then the fourth value sets the final chip state and enables | ||
85 | * desired. | ||
86 | */ | ||
87 | |||
88 | static int n2rng_hv_err_trans(unsigned long hv_err) | ||
89 | { | ||
90 | switch (hv_err) { | ||
91 | case HV_EOK: | ||
92 | return 0; | ||
93 | case HV_EWOULDBLOCK: | ||
94 | return -EAGAIN; | ||
95 | case HV_ENOACCESS: | ||
96 | return -EPERM; | ||
97 | case HV_EIO: | ||
98 | return -EIO; | ||
99 | case HV_EBUSY: | ||
100 | return -EBUSY; | ||
101 | case HV_EBADALIGN: | ||
102 | case HV_ENORADDR: | ||
103 | return -EFAULT; | ||
104 | default: | ||
105 | return -EINVAL; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static unsigned long n2rng_generic_read_control_v2(unsigned long ra, | ||
110 | unsigned long unit) | ||
111 | { | ||
112 | unsigned long hv_err, state, ticks, watchdog_delta, watchdog_status; | ||
113 | int block = 0, busy = 0; | ||
114 | |||
115 | while (1) { | ||
116 | hv_err = sun4v_rng_ctl_read_v2(ra, unit, &state, | ||
117 | &ticks, | ||
118 | &watchdog_delta, | ||
119 | &watchdog_status); | ||
120 | if (hv_err == HV_EOK) | ||
121 | break; | ||
122 | |||
123 | if (hv_err == HV_EBUSY) { | ||
124 | if (++busy >= N2RNG_BUSY_LIMIT) | ||
125 | break; | ||
126 | |||
127 | udelay(1); | ||
128 | } else if (hv_err == HV_EWOULDBLOCK) { | ||
129 | if (++block >= N2RNG_BLOCK_LIMIT) | ||
130 | break; | ||
131 | |||
132 | __delay(ticks); | ||
133 | } else | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | return hv_err; | ||
138 | } | ||
139 | |||
140 | /* In multi-socket situations, the hypervisor might need to | ||
141 | * queue up the RNG control register write if it's for a unit | ||
142 | * that is on a cpu socket other than the one we are executing on. | ||
143 | * | ||
144 | * We poll here waiting for a successful read of that control | ||
145 | * register to make sure the write has been actually performed. | ||
146 | */ | ||
147 | static unsigned long n2rng_control_settle_v2(struct n2rng *np, int unit) | ||
148 | { | ||
149 | unsigned long ra = __pa(&np->scratch_control[0]); | ||
150 | |||
151 | return n2rng_generic_read_control_v2(ra, unit); | ||
152 | } | ||
153 | |||
154 | static unsigned long n2rng_write_ctl_one(struct n2rng *np, int unit, | ||
155 | unsigned long state, | ||
156 | unsigned long control_ra, | ||
157 | unsigned long watchdog_timeout, | ||
158 | unsigned long *ticks) | ||
159 | { | ||
160 | unsigned long hv_err; | ||
161 | |||
162 | if (np->hvapi_major == 1) { | ||
163 | hv_err = sun4v_rng_ctl_write_v1(control_ra, state, | ||
164 | watchdog_timeout, ticks); | ||
165 | } else { | ||
166 | hv_err = sun4v_rng_ctl_write_v2(control_ra, state, | ||
167 | watchdog_timeout, unit); | ||
168 | if (hv_err == HV_EOK) | ||
169 | hv_err = n2rng_control_settle_v2(np, unit); | ||
170 | *ticks = N2RNG_ACCUM_CYCLES_DEFAULT; | ||
171 | } | ||
172 | |||
173 | return hv_err; | ||
174 | } | ||
175 | |||
176 | static int n2rng_generic_read_data(unsigned long data_ra) | ||
177 | { | ||
178 | unsigned long ticks, hv_err; | ||
179 | int block = 0, hcheck = 0; | ||
180 | |||
181 | while (1) { | ||
182 | hv_err = sun4v_rng_data_read(data_ra, &ticks); | ||
183 | if (hv_err == HV_EOK) | ||
184 | return 0; | ||
185 | |||
186 | if (hv_err == HV_EWOULDBLOCK) { | ||
187 | if (++block >= N2RNG_BLOCK_LIMIT) | ||
188 | return -EWOULDBLOCK; | ||
189 | __delay(ticks); | ||
190 | } else if (hv_err == HV_ENOACCESS) { | ||
191 | return -EPERM; | ||
192 | } else if (hv_err == HV_EIO) { | ||
193 | if (++hcheck >= N2RNG_HCHECK_LIMIT) | ||
194 | return -EIO; | ||
195 | udelay(10000); | ||
196 | } else | ||
197 | return -ENODEV; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static unsigned long n2rng_read_diag_data_one(struct n2rng *np, | ||
202 | unsigned long unit, | ||
203 | unsigned long data_ra, | ||
204 | unsigned long data_len, | ||
205 | unsigned long *ticks) | ||
206 | { | ||
207 | unsigned long hv_err; | ||
208 | |||
209 | if (np->hvapi_major == 1) { | ||
210 | hv_err = sun4v_rng_data_read_diag_v1(data_ra, data_len, ticks); | ||
211 | } else { | ||
212 | hv_err = sun4v_rng_data_read_diag_v2(data_ra, data_len, | ||
213 | unit, ticks); | ||
214 | if (!*ticks) | ||
215 | *ticks = N2RNG_ACCUM_CYCLES_DEFAULT; | ||
216 | } | ||
217 | return hv_err; | ||
218 | } | ||
219 | |||
220 | static int n2rng_generic_read_diag_data(struct n2rng *np, | ||
221 | unsigned long unit, | ||
222 | unsigned long data_ra, | ||
223 | unsigned long data_len) | ||
224 | { | ||
225 | unsigned long ticks, hv_err; | ||
226 | int block = 0; | ||
227 | |||
228 | while (1) { | ||
229 | hv_err = n2rng_read_diag_data_one(np, unit, | ||
230 | data_ra, data_len, | ||
231 | &ticks); | ||
232 | if (hv_err == HV_EOK) | ||
233 | return 0; | ||
234 | |||
235 | if (hv_err == HV_EWOULDBLOCK) { | ||
236 | if (++block >= N2RNG_BLOCK_LIMIT) | ||
237 | return -EWOULDBLOCK; | ||
238 | __delay(ticks); | ||
239 | } else if (hv_err == HV_ENOACCESS) { | ||
240 | return -EPERM; | ||
241 | } else if (hv_err == HV_EIO) { | ||
242 | return -EIO; | ||
243 | } else | ||
244 | return -ENODEV; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | |||
249 | static int n2rng_generic_write_control(struct n2rng *np, | ||
250 | unsigned long control_ra, | ||
251 | unsigned long unit, | ||
252 | unsigned long state) | ||
253 | { | ||
254 | unsigned long hv_err, ticks; | ||
255 | int block = 0, busy = 0; | ||
256 | |||
257 | while (1) { | ||
258 | hv_err = n2rng_write_ctl_one(np, unit, state, control_ra, | ||
259 | np->wd_timeo, &ticks); | ||
260 | if (hv_err == HV_EOK) | ||
261 | return 0; | ||
262 | |||
263 | if (hv_err == HV_EWOULDBLOCK) { | ||
264 | if (++block >= N2RNG_BLOCK_LIMIT) | ||
265 | return -EWOULDBLOCK; | ||
266 | __delay(ticks); | ||
267 | } else if (hv_err == HV_EBUSY) { | ||
268 | if (++busy >= N2RNG_BUSY_LIMIT) | ||
269 | return -EBUSY; | ||
270 | udelay(1); | ||
271 | } else | ||
272 | return -ENODEV; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* Just try to see if we can successfully access the control register | ||
277 | * of the RNG on the domain on which we are currently executing. | ||
278 | */ | ||
279 | static int n2rng_try_read_ctl(struct n2rng *np) | ||
280 | { | ||
281 | unsigned long hv_err; | ||
282 | unsigned long x; | ||
283 | |||
284 | if (np->hvapi_major == 1) { | ||
285 | hv_err = sun4v_rng_get_diag_ctl(); | ||
286 | } else { | ||
287 | /* We purposefully give invalid arguments, HV_NOACCESS | ||
288 | * is higher priority than the errors we'd get from | ||
289 | * these other cases, and that's the error we are | ||
290 | * truly interested in. | ||
291 | */ | ||
292 | hv_err = sun4v_rng_ctl_read_v2(0UL, ~0UL, &x, &x, &x, &x); | ||
293 | switch (hv_err) { | ||
294 | case HV_EWOULDBLOCK: | ||
295 | case HV_ENOACCESS: | ||
296 | break; | ||
297 | default: | ||
298 | hv_err = HV_EOK; | ||
299 | break; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | return n2rng_hv_err_trans(hv_err); | ||
304 | } | ||
305 | |||
306 | #define CONTROL_DEFAULT_BASE \ | ||
307 | ((2 << RNG_CTL_ASEL_SHIFT) | \ | ||
308 | (N2RNG_ACCUM_CYCLES_DEFAULT << RNG_CTL_WAIT_SHIFT) | \ | ||
309 | RNG_CTL_LFSR) | ||
310 | |||
311 | #define CONTROL_DEFAULT_0 \ | ||
312 | (CONTROL_DEFAULT_BASE | \ | ||
313 | (1 << RNG_CTL_VCO_SHIFT) | \ | ||
314 | RNG_CTL_ES1) | ||
315 | #define CONTROL_DEFAULT_1 \ | ||
316 | (CONTROL_DEFAULT_BASE | \ | ||
317 | (2 << RNG_CTL_VCO_SHIFT) | \ | ||
318 | RNG_CTL_ES2) | ||
319 | #define CONTROL_DEFAULT_2 \ | ||
320 | (CONTROL_DEFAULT_BASE | \ | ||
321 | (3 << RNG_CTL_VCO_SHIFT) | \ | ||
322 | RNG_CTL_ES3) | ||
323 | #define CONTROL_DEFAULT_3 \ | ||
324 | (CONTROL_DEFAULT_BASE | \ | ||
325 | RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3) | ||
326 | |||
327 | static void n2rng_control_swstate_init(struct n2rng *np) | ||
328 | { | ||
329 | int i; | ||
330 | |||
331 | np->flags |= N2RNG_FLAG_CONTROL; | ||
332 | |||
333 | np->health_check_sec = N2RNG_HEALTH_CHECK_SEC_DEFAULT; | ||
334 | np->accum_cycles = N2RNG_ACCUM_CYCLES_DEFAULT; | ||
335 | np->wd_timeo = N2RNG_WD_TIMEO_DEFAULT; | ||
336 | |||
337 | for (i = 0; i < np->num_units; i++) { | ||
338 | struct n2rng_unit *up = &np->units[i]; | ||
339 | |||
340 | up->control[0] = CONTROL_DEFAULT_0; | ||
341 | up->control[1] = CONTROL_DEFAULT_1; | ||
342 | up->control[2] = CONTROL_DEFAULT_2; | ||
343 | up->control[3] = CONTROL_DEFAULT_3; | ||
344 | } | ||
345 | |||
346 | np->hv_state = HV_RNG_STATE_UNCONFIGURED; | ||
347 | } | ||
348 | |||
349 | static int n2rng_grab_diag_control(struct n2rng *np) | ||
350 | { | ||
351 | int i, busy_count, err = -ENODEV; | ||
352 | |||
353 | busy_count = 0; | ||
354 | for (i = 0; i < 100; i++) { | ||
355 | err = n2rng_try_read_ctl(np); | ||
356 | if (err != -EAGAIN) | ||
357 | break; | ||
358 | |||
359 | if (++busy_count > 100) { | ||
360 | dev_err(&np->op->dev, | ||
361 | "Grab diag control timeout.\n"); | ||
362 | return -ENODEV; | ||
363 | } | ||
364 | |||
365 | udelay(1); | ||
366 | } | ||
367 | |||
368 | return err; | ||
369 | } | ||
370 | |||
371 | static int n2rng_init_control(struct n2rng *np) | ||
372 | { | ||
373 | int err = n2rng_grab_diag_control(np); | ||
374 | |||
375 | /* Not in the control domain, that's OK we are only a consumer | ||
376 | * of the RNG data, we don't setup and program it. | ||
377 | */ | ||
378 | if (err == -EPERM) | ||
379 | return 0; | ||
380 | if (err) | ||
381 | return err; | ||
382 | |||
383 | n2rng_control_swstate_init(np); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int n2rng_data_read(struct hwrng *rng, u32 *data) | ||
389 | { | ||
390 | struct n2rng *np = (struct n2rng *) rng->priv; | ||
391 | unsigned long ra = __pa(&np->test_data); | ||
392 | int len; | ||
393 | |||
394 | if (!(np->flags & N2RNG_FLAG_READY)) { | ||
395 | len = 0; | ||
396 | } else if (np->flags & N2RNG_FLAG_BUFFER_VALID) { | ||
397 | np->flags &= ~N2RNG_FLAG_BUFFER_VALID; | ||
398 | *data = np->buffer; | ||
399 | len = 4; | ||
400 | } else { | ||
401 | int err = n2rng_generic_read_data(ra); | ||
402 | if (!err) { | ||
403 | np->buffer = np->test_data >> 32; | ||
404 | *data = np->test_data & 0xffffffff; | ||
405 | len = 4; | ||
406 | } else { | ||
407 | dev_err(&np->op->dev, "RNG error, restesting\n"); | ||
408 | np->flags &= ~N2RNG_FLAG_READY; | ||
409 | if (!(np->flags & N2RNG_FLAG_SHUTDOWN)) | ||
410 | schedule_delayed_work(&np->work, 0); | ||
411 | len = 0; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | return len; | ||
416 | } | ||
417 | |||
418 | /* On a guest node, just make sure we can read random data properly. | ||
419 | * If a control node reboots or reloads it's n2rng driver, this won't | ||
420 | * work during that time. So we have to keep probing until the device | ||
421 | * becomes usable. | ||
422 | */ | ||
423 | static int n2rng_guest_check(struct n2rng *np) | ||
424 | { | ||
425 | unsigned long ra = __pa(&np->test_data); | ||
426 | |||
427 | return n2rng_generic_read_data(ra); | ||
428 | } | ||
429 | |||
430 | static int n2rng_entropy_diag_read(struct n2rng *np, unsigned long unit, | ||
431 | u64 *pre_control, u64 pre_state, | ||
432 | u64 *buffer, unsigned long buf_len, | ||
433 | u64 *post_control, u64 post_state) | ||
434 | { | ||
435 | unsigned long post_ctl_ra = __pa(post_control); | ||
436 | unsigned long pre_ctl_ra = __pa(pre_control); | ||
437 | unsigned long buffer_ra = __pa(buffer); | ||
438 | int err; | ||
439 | |||
440 | err = n2rng_generic_write_control(np, pre_ctl_ra, unit, pre_state); | ||
441 | if (err) | ||
442 | return err; | ||
443 | |||
444 | err = n2rng_generic_read_diag_data(np, unit, | ||
445 | buffer_ra, buf_len); | ||
446 | |||
447 | (void) n2rng_generic_write_control(np, post_ctl_ra, unit, | ||
448 | post_state); | ||
449 | |||
450 | return err; | ||
451 | } | ||
452 | |||
453 | static u64 advance_polynomial(u64 poly, u64 val, int count) | ||
454 | { | ||
455 | int i; | ||
456 | |||
457 | for (i = 0; i < count; i++) { | ||
458 | int highbit_set = ((s64)val < 0); | ||
459 | |||
460 | val <<= 1; | ||
461 | if (highbit_set) | ||
462 | val ^= poly; | ||
463 | } | ||
464 | |||
465 | return val; | ||
466 | } | ||
467 | |||
468 | static int n2rng_test_buffer_find(struct n2rng *np, u64 val) | ||
469 | { | ||
470 | int i, count = 0; | ||
471 | |||
472 | /* Purposefully skip over the first word. */ | ||
473 | for (i = 1; i < SELFTEST_BUFFER_WORDS; i++) { | ||
474 | if (np->test_buffer[i] == val) | ||
475 | count++; | ||
476 | } | ||
477 | return count; | ||
478 | } | ||
479 | |||
480 | static void n2rng_dump_test_buffer(struct n2rng *np) | ||
481 | { | ||
482 | int i; | ||
483 | |||
484 | for (i = 0; i < SELFTEST_BUFFER_WORDS; i++) | ||
485 | dev_err(&np->op->dev, "Test buffer slot %d [0x%016lx]\n", | ||
486 | i, np->test_buffer[i]); | ||
487 | } | ||
488 | |||
489 | static int n2rng_check_selftest_buffer(struct n2rng *np, unsigned long unit) | ||
490 | { | ||
491 | u64 val = SELFTEST_VAL; | ||
492 | int err, matches, limit; | ||
493 | |||
494 | matches = 0; | ||
495 | for (limit = 0; limit < SELFTEST_LOOPS_MAX; limit++) { | ||
496 | matches += n2rng_test_buffer_find(np, val); | ||
497 | if (matches >= SELFTEST_MATCH_GOAL) | ||
498 | break; | ||
499 | val = advance_polynomial(SELFTEST_POLY, val, 1); | ||
500 | } | ||
501 | |||
502 | err = 0; | ||
503 | if (limit >= SELFTEST_LOOPS_MAX) { | ||
504 | err = -ENODEV; | ||
505 | dev_err(&np->op->dev, "Selftest failed on unit %lu\n", unit); | ||
506 | n2rng_dump_test_buffer(np); | ||
507 | } else | ||
508 | dev_info(&np->op->dev, "Selftest passed on unit %lu\n", unit); | ||
509 | |||
510 | return err; | ||
511 | } | ||
512 | |||
513 | static int n2rng_control_selftest(struct n2rng *np, unsigned long unit) | ||
514 | { | ||
515 | int err; | ||
516 | |||
517 | np->test_control[0] = (0x2 << RNG_CTL_ASEL_SHIFT); | ||
518 | np->test_control[1] = (0x2 << RNG_CTL_ASEL_SHIFT); | ||
519 | np->test_control[2] = (0x2 << RNG_CTL_ASEL_SHIFT); | ||
520 | np->test_control[3] = ((0x2 << RNG_CTL_ASEL_SHIFT) | | ||
521 | RNG_CTL_LFSR | | ||
522 | ((SELFTEST_TICKS - 2) << RNG_CTL_WAIT_SHIFT)); | ||
523 | |||
524 | |||
525 | err = n2rng_entropy_diag_read(np, unit, np->test_control, | ||
526 | HV_RNG_STATE_HEALTHCHECK, | ||
527 | np->test_buffer, | ||
528 | sizeof(np->test_buffer), | ||
529 | &np->units[unit].control[0], | ||
530 | np->hv_state); | ||
531 | if (err) | ||
532 | return err; | ||
533 | |||
534 | return n2rng_check_selftest_buffer(np, unit); | ||
535 | } | ||
536 | |||
537 | static int n2rng_control_check(struct n2rng *np) | ||
538 | { | ||
539 | int i; | ||
540 | |||
541 | for (i = 0; i < np->num_units; i++) { | ||
542 | int err = n2rng_control_selftest(np, i); | ||
543 | if (err) | ||
544 | return err; | ||
545 | } | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | /* The sanity checks passed, install the final configuration into the | ||
550 | * chip, it's ready to use. | ||
551 | */ | ||
552 | static int n2rng_control_configure_units(struct n2rng *np) | ||
553 | { | ||
554 | int unit, err; | ||
555 | |||
556 | err = 0; | ||
557 | for (unit = 0; unit < np->num_units; unit++) { | ||
558 | struct n2rng_unit *up = &np->units[unit]; | ||
559 | unsigned long ctl_ra = __pa(&up->control[0]); | ||
560 | int esrc; | ||
561 | u64 base; | ||
562 | |||
563 | base = ((np->accum_cycles << RNG_CTL_WAIT_SHIFT) | | ||
564 | (2 << RNG_CTL_ASEL_SHIFT) | | ||
565 | RNG_CTL_LFSR); | ||
566 | |||
567 | /* XXX This isn't the best. We should fetch a bunch | ||
568 | * XXX of words using each entropy source combined XXX | ||
569 | * with each VCO setting, and see which combinations | ||
570 | * XXX give the best random data. | ||
571 | */ | ||
572 | for (esrc = 0; esrc < 3; esrc++) | ||
573 | up->control[esrc] = base | | ||
574 | (esrc << RNG_CTL_VCO_SHIFT) | | ||
575 | (RNG_CTL_ES1 << esrc); | ||
576 | |||
577 | up->control[3] = base | | ||
578 | (RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3); | ||
579 | |||
580 | err = n2rng_generic_write_control(np, ctl_ra, unit, | ||
581 | HV_RNG_STATE_CONFIGURED); | ||
582 | if (err) | ||
583 | break; | ||
584 | } | ||
585 | |||
586 | return err; | ||
587 | } | ||
588 | |||
589 | static void n2rng_work(struct work_struct *work) | ||
590 | { | ||
591 | struct n2rng *np = container_of(work, struct n2rng, work.work); | ||
592 | int err = 0; | ||
593 | |||
594 | if (!(np->flags & N2RNG_FLAG_CONTROL)) { | ||
595 | err = n2rng_guest_check(np); | ||
596 | } else { | ||
597 | preempt_disable(); | ||
598 | err = n2rng_control_check(np); | ||
599 | preempt_enable(); | ||
600 | |||
601 | if (!err) | ||
602 | err = n2rng_control_configure_units(np); | ||
603 | } | ||
604 | |||
605 | if (!err) { | ||
606 | np->flags |= N2RNG_FLAG_READY; | ||
607 | dev_info(&np->op->dev, "RNG ready\n"); | ||
608 | } | ||
609 | |||
610 | if (err && !(np->flags & N2RNG_FLAG_SHUTDOWN)) | ||
611 | schedule_delayed_work(&np->work, HZ * 2); | ||
612 | } | ||
613 | |||
614 | static void __devinit n2rng_driver_version(void) | ||
615 | { | ||
616 | static int n2rng_version_printed; | ||
617 | |||
618 | if (n2rng_version_printed++ == 0) | ||
619 | pr_info("%s", version); | ||
620 | } | ||
621 | |||
622 | static int __devinit n2rng_probe(struct of_device *op, | ||
623 | const struct of_device_id *match) | ||
624 | { | ||
625 | int victoria_falls = (match->data != NULL); | ||
626 | int err = -ENOMEM; | ||
627 | struct n2rng *np; | ||
628 | |||
629 | n2rng_driver_version(); | ||
630 | |||
631 | np = kzalloc(sizeof(*np), GFP_KERNEL); | ||
632 | if (!np) | ||
633 | goto out; | ||
634 | np->op = op; | ||
635 | |||
636 | INIT_DELAYED_WORK(&np->work, n2rng_work); | ||
637 | |||
638 | if (victoria_falls) | ||
639 | np->flags |= N2RNG_FLAG_VF; | ||
640 | |||
641 | err = -ENODEV; | ||
642 | np->hvapi_major = 2; | ||
643 | if (sun4v_hvapi_register(HV_GRP_RNG, | ||
644 | np->hvapi_major, | ||
645 | &np->hvapi_minor)) { | ||
646 | np->hvapi_major = 1; | ||
647 | if (sun4v_hvapi_register(HV_GRP_RNG, | ||
648 | np->hvapi_major, | ||
649 | &np->hvapi_minor)) { | ||
650 | dev_err(&op->dev, "Cannot register suitable " | ||
651 | "HVAPI version.\n"); | ||
652 | goto out_free; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | if (np->flags & N2RNG_FLAG_VF) { | ||
657 | if (np->hvapi_major < 2) { | ||
658 | dev_err(&op->dev, "VF RNG requires HVAPI major " | ||
659 | "version 2 or later, got %lu\n", | ||
660 | np->hvapi_major); | ||
661 | goto out_hvapi_unregister; | ||
662 | } | ||
663 | np->num_units = of_getintprop_default(op->node, | ||
664 | "rng-#units", 0); | ||
665 | if (!np->num_units) { | ||
666 | dev_err(&op->dev, "VF RNG lacks rng-#units property\n"); | ||
667 | goto out_hvapi_unregister; | ||
668 | } | ||
669 | } else | ||
670 | np->num_units = 1; | ||
671 | |||
672 | dev_info(&op->dev, "Registered RNG HVAPI major %lu minor %lu\n", | ||
673 | np->hvapi_major, np->hvapi_minor); | ||
674 | |||
675 | np->units = kzalloc(sizeof(struct n2rng_unit) * np->num_units, | ||
676 | GFP_KERNEL); | ||
677 | err = -ENOMEM; | ||
678 | if (!np->units) | ||
679 | goto out_hvapi_unregister; | ||
680 | |||
681 | err = n2rng_init_control(np); | ||
682 | if (err) | ||
683 | goto out_free_units; | ||
684 | |||
685 | dev_info(&op->dev, "Found %s RNG, units: %d\n", | ||
686 | ((np->flags & N2RNG_FLAG_VF) ? | ||
687 | "Victoria Falls" : "Niagara2"), | ||
688 | np->num_units); | ||
689 | |||
690 | np->hwrng.name = "n2rng"; | ||
691 | np->hwrng.data_read = n2rng_data_read; | ||
692 | np->hwrng.priv = (unsigned long) np; | ||
693 | |||
694 | err = hwrng_register(&np->hwrng); | ||
695 | if (err) | ||
696 | goto out_free_units; | ||
697 | |||
698 | dev_set_drvdata(&op->dev, np); | ||
699 | |||
700 | schedule_delayed_work(&np->work, 0); | ||
701 | |||
702 | return 0; | ||
703 | |||
704 | out_free_units: | ||
705 | kfree(np->units); | ||
706 | np->units = NULL; | ||
707 | |||
708 | out_hvapi_unregister: | ||
709 | sun4v_hvapi_unregister(HV_GRP_RNG); | ||
710 | |||
711 | out_free: | ||
712 | kfree(np); | ||
713 | out: | ||
714 | return err; | ||
715 | } | ||
716 | |||
717 | static int __devexit n2rng_remove(struct of_device *op) | ||
718 | { | ||
719 | struct n2rng *np = dev_get_drvdata(&op->dev); | ||
720 | |||
721 | np->flags |= N2RNG_FLAG_SHUTDOWN; | ||
722 | |||
723 | cancel_delayed_work_sync(&np->work); | ||
724 | |||
725 | hwrng_unregister(&np->hwrng); | ||
726 | |||
727 | sun4v_hvapi_unregister(HV_GRP_RNG); | ||
728 | |||
729 | kfree(np->units); | ||
730 | np->units = NULL; | ||
731 | |||
732 | kfree(np); | ||
733 | |||
734 | dev_set_drvdata(&op->dev, NULL); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static struct of_device_id n2rng_match[] = { | ||
740 | { | ||
741 | .name = "random-number-generator", | ||
742 | .compatible = "SUNW,n2-rng", | ||
743 | }, | ||
744 | { | ||
745 | .name = "random-number-generator", | ||
746 | .compatible = "SUNW,vf-rng", | ||
747 | .data = (void *) 1, | ||
748 | }, | ||
749 | {}, | ||
750 | }; | ||
751 | MODULE_DEVICE_TABLE(of, n2rng_match); | ||
752 | |||
753 | static struct of_platform_driver n2rng_driver = { | ||
754 | .name = "n2rng", | ||
755 | .match_table = n2rng_match, | ||
756 | .probe = n2rng_probe, | ||
757 | .remove = __devexit_p(n2rng_remove), | ||
758 | }; | ||
759 | |||
760 | static int __init n2rng_init(void) | ||
761 | { | ||
762 | return of_register_driver(&n2rng_driver, &of_bus_type); | ||
763 | } | ||
764 | |||
765 | static void __exit n2rng_exit(void) | ||
766 | { | ||
767 | of_unregister_driver(&n2rng_driver); | ||
768 | } | ||
769 | |||
770 | module_init(n2rng_init); | ||
771 | module_exit(n2rng_exit); | ||
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h new file mode 100644 index 000000000000..a2b81e7bfc18 --- /dev/null +++ b/drivers/char/hw_random/n2rng.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /* n2rng.h: Niagara2 RNG defines. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #ifndef _N2RNG_H | ||
7 | #define _N2RNG_H | ||
8 | |||
9 | #define RNG_CTL_WAIT 0x0000000001fffe00ULL /* Minimum wait time */ | ||
10 | #define RNG_CTL_WAIT_SHIFT 9 | ||
11 | #define RNG_CTL_BYPASS 0x0000000000000100ULL /* VCO voltage source */ | ||
12 | #define RNG_CTL_VCO 0x00000000000000c0ULL /* VCO rate control */ | ||
13 | #define RNG_CTL_VCO_SHIFT 6 | ||
14 | #define RNG_CTL_ASEL 0x0000000000000030ULL /* Analog MUX select */ | ||
15 | #define RNG_CTL_ASEL_SHIFT 4 | ||
16 | #define RNG_CTL_LFSR 0x0000000000000008ULL /* Use LFSR or plain shift */ | ||
17 | #define RNG_CTL_ES3 0x0000000000000004ULL /* Enable entropy source 3 */ | ||
18 | #define RNG_CTL_ES2 0x0000000000000002ULL /* Enable entropy source 2 */ | ||
19 | #define RNG_CTL_ES1 0x0000000000000001ULL /* Enable entropy source 1 */ | ||
20 | |||
21 | #define HV_FAST_RNG_GET_DIAG_CTL 0x130 | ||
22 | #define HV_FAST_RNG_CTL_READ 0x131 | ||
23 | #define HV_FAST_RNG_CTL_WRITE 0x132 | ||
24 | #define HV_FAST_RNG_DATA_READ_DIAG 0x133 | ||
25 | #define HV_FAST_RNG_DATA_READ 0x134 | ||
26 | |||
27 | #define HV_RNG_STATE_UNCONFIGURED 0 | ||
28 | #define HV_RNG_STATE_CONFIGURED 1 | ||
29 | #define HV_RNG_STATE_HEALTHCHECK 2 | ||
30 | #define HV_RNG_STATE_ERROR 3 | ||
31 | |||
32 | #define HV_RNG_NUM_CONTROL 4 | ||
33 | |||
34 | #ifndef __ASSEMBLY__ | ||
35 | extern unsigned long sun4v_rng_get_diag_ctl(void); | ||
36 | extern unsigned long sun4v_rng_ctl_read_v1(unsigned long ctl_regs_ra, | ||
37 | unsigned long *state, | ||
38 | unsigned long *tick_delta); | ||
39 | extern unsigned long sun4v_rng_ctl_read_v2(unsigned long ctl_regs_ra, | ||
40 | unsigned long unit, | ||
41 | unsigned long *state, | ||
42 | unsigned long *tick_delta, | ||
43 | unsigned long *watchdog, | ||
44 | unsigned long *write_status); | ||
45 | extern unsigned long sun4v_rng_ctl_write_v1(unsigned long ctl_regs_ra, | ||
46 | unsigned long state, | ||
47 | unsigned long write_timeout, | ||
48 | unsigned long *tick_delta); | ||
49 | extern unsigned long sun4v_rng_ctl_write_v2(unsigned long ctl_regs_ra, | ||
50 | unsigned long state, | ||
51 | unsigned long write_timeout, | ||
52 | unsigned long unit); | ||
53 | extern unsigned long sun4v_rng_data_read_diag_v1(unsigned long data_ra, | ||
54 | unsigned long len, | ||
55 | unsigned long *tick_delta); | ||
56 | extern unsigned long sun4v_rng_data_read_diag_v2(unsigned long data_ra, | ||
57 | unsigned long len, | ||
58 | unsigned long unit, | ||
59 | unsigned long *tick_delta); | ||
60 | extern unsigned long sun4v_rng_data_read(unsigned long data_ra, | ||
61 | unsigned long *tick_delta); | ||
62 | |||
63 | struct n2rng_unit { | ||
64 | u64 control[HV_RNG_NUM_CONTROL]; | ||
65 | }; | ||
66 | |||
67 | struct n2rng { | ||
68 | struct of_device *op; | ||
69 | |||
70 | unsigned long flags; | ||
71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ | ||
72 | #define N2RNG_FLAG_CONTROL 0x00000002 /* Operating in control domain */ | ||
73 | #define N2RNG_FLAG_READY 0x00000008 /* Ready for hw-rng layer */ | ||
74 | #define N2RNG_FLAG_SHUTDOWN 0x00000010 /* Driver unregistering */ | ||
75 | #define N2RNG_FLAG_BUFFER_VALID 0x00000020 /* u32 buffer holds valid data */ | ||
76 | |||
77 | int num_units; | ||
78 | struct n2rng_unit *units; | ||
79 | |||
80 | struct hwrng hwrng; | ||
81 | u32 buffer; | ||
82 | |||
83 | /* Registered hypervisor group API major and minor version. */ | ||
84 | unsigned long hvapi_major; | ||
85 | unsigned long hvapi_minor; | ||
86 | |||
87 | struct delayed_work work; | ||
88 | |||
89 | unsigned long hv_state; /* HV_RNG_STATE_foo */ | ||
90 | |||
91 | unsigned long health_check_sec; | ||
92 | unsigned long accum_cycles; | ||
93 | unsigned long wd_timeo; | ||
94 | #define N2RNG_HEALTH_CHECK_SEC_DEFAULT 0 | ||
95 | #define N2RNG_ACCUM_CYCLES_DEFAULT 2048 | ||
96 | #define N2RNG_WD_TIMEO_DEFAULT 0 | ||
97 | |||
98 | u64 scratch_control[HV_RNG_NUM_CONTROL]; | ||
99 | |||
100 | #define SELFTEST_TICKS 38859 | ||
101 | #define SELFTEST_VAL ((u64)0xB8820C7BD387E32C) | ||
102 | #define SELFTEST_POLY ((u64)0x231DCEE91262B8A3) | ||
103 | #define SELFTEST_MATCH_GOAL 6 | ||
104 | #define SELFTEST_LOOPS_MAX 40000 | ||
105 | #define SELFTEST_BUFFER_WORDS 8 | ||
106 | |||
107 | u64 test_data; | ||
108 | u64 test_control[HV_RNG_NUM_CONTROL]; | ||
109 | u64 test_buffer[SELFTEST_BUFFER_WORDS]; | ||
110 | }; | ||
111 | |||
112 | #define N2RNG_BLOCK_LIMIT 60000 | ||
113 | #define N2RNG_BUSY_LIMIT 100 | ||
114 | #define N2RNG_HCHECK_LIMIT 100 | ||
115 | |||
116 | #endif /* !(__ASSEMBLY__) */ | ||
117 | |||
118 | #endif /* _N2RNG_H */ | ||
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 5dc74404058f..689f9dcd3b86 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 *); | |||
203 | 203 | ||
204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); | 204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); |
205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); | 205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); |
206 | static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); | 206 | static long ip2_ipl_ioctl(struct file *, UINT, ULONG); |
207 | static int ip2_ipl_open(struct inode *, struct file *); | 207 | static int ip2_ipl_open(struct inode *, struct file *); |
208 | 208 | ||
209 | static int DumpTraceBuffer(char __user *, int); | 209 | static int DumpTraceBuffer(char __user *, int); |
@@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = { | |||
236 | .owner = THIS_MODULE, | 236 | .owner = THIS_MODULE, |
237 | .read = ip2_ipl_read, | 237 | .read = ip2_ipl_read, |
238 | .write = ip2_ipl_write, | 238 | .write = ip2_ipl_write, |
239 | .ioctl = ip2_ipl_ioctl, | 239 | .unlocked_ioctl = ip2_ipl_ioctl, |
240 | .open = ip2_ipl_open, | 240 | .open = ip2_ipl_open, |
241 | }; | 241 | }; |
242 | 242 | ||
@@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp) | |||
718 | } | 718 | } |
719 | 719 | ||
720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { | 720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { |
721 | device_create(ip2_class, NULL, | 721 | device_create_drvdata(ip2_class, NULL, |
722 | MKDEV(IP2_IPL_MAJOR, 4 * i), | 722 | MKDEV(IP2_IPL_MAJOR, 4 * i), |
723 | "ipl%d", i); | 723 | NULL, "ipl%d", i); |
724 | device_create(ip2_class, NULL, | 724 | device_create_drvdata(ip2_class, NULL, |
725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | 725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), |
726 | "stat%d", i); | 726 | NULL, "stat%d", i); |
727 | 727 | ||
728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
729 | { | 729 | { |
@@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t | |||
2845 | /* */ | 2845 | /* */ |
2846 | /* */ | 2846 | /* */ |
2847 | /******************************************************************************/ | 2847 | /******************************************************************************/ |
2848 | static int | 2848 | static long |
2849 | ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | 2849 | ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) |
2850 | { | 2850 | { |
2851 | unsigned int iplminor = iminor(pInode); | 2851 | unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); |
2852 | int rc = 0; | 2852 | int rc = 0; |
2853 | void __user *argp = (void __user *)arg; | 2853 | void __user *argp = (void __user *)arg; |
2854 | ULONG __user *pIndex = argp; | 2854 | ULONG __user *pIndex = argp; |
@@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | |||
2859 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); | 2859 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); |
2860 | #endif | 2860 | #endif |
2861 | 2861 | ||
2862 | lock_kernel(); | ||
2863 | |||
2862 | switch ( iplminor ) { | 2864 | switch ( iplminor ) { |
2863 | case 0: // IPL device | 2865 | case 0: // IPL device |
2864 | rc = -EINVAL; | 2866 | rc = -EINVAL; |
@@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | |||
2919 | rc = -ENODEV; | 2921 | rc = -ENODEV; |
2920 | break; | 2922 | break; |
2921 | } | 2923 | } |
2924 | unlock_kernel(); | ||
2922 | return rc; | 2925 | return rc; |
2923 | } | 2926 | } |
2924 | 2927 | ||
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index c11a40483459..64e1c169e826 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device) | |||
871 | entry->dev = dev; | 871 | entry->dev = dev; |
872 | 872 | ||
873 | mutex_lock(®_list_mutex); | 873 | mutex_lock(®_list_mutex); |
874 | device_create(ipmi_class, device, dev, "ipmi%d", if_num); | 874 | device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num); |
875 | list_add(&entry->link, ®_list); | 875 | list_add(&entry->link, ®_list); |
876 | mutex_unlock(®_list_mutex); | 876 | mutex_unlock(®_list_mutex); |
877 | } | 877 | } |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 192688344ed2..f52931e1c16e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -66,8 +66,8 @@ | |||
66 | #include <linux/ctype.h> | 66 | #include <linux/ctype.h> |
67 | 67 | ||
68 | #ifdef CONFIG_PPC_OF | 68 | #ifdef CONFIG_PPC_OF |
69 | #include <asm/of_device.h> | 69 | #include <linux/of_device.h> |
70 | #include <asm/of_platform.h> | 70 | #include <linux/of_platform.h> |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #define PFX "ipmi_si: " | 73 | #define PFX "ipmi_si: " |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index d4281df10c22..8f7cc190b62d 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -1181,14 +1181,17 @@ static int isicom_chars_in_buffer(struct tty_struct *tty) | |||
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | /* ioctl et all */ | 1183 | /* ioctl et all */ |
1184 | static inline void isicom_send_break(struct isi_port *port, | 1184 | static int isicom_send_break(struct tty_struct *tty, int length) |
1185 | unsigned long length) | ||
1186 | { | 1185 | { |
1186 | struct isi_port *port = tty->driver_data; | ||
1187 | struct isi_board *card = port->card; | 1187 | struct isi_board *card = port->card; |
1188 | unsigned long base = card->base; | 1188 | unsigned long base = card->base; |
1189 | 1189 | ||
1190 | if (length == -1) | ||
1191 | return -EOPNOTSUPP; | ||
1192 | |||
1190 | if (!lock_card(card)) | 1193 | if (!lock_card(card)) |
1191 | return; | 1194 | return -EINVAL; |
1192 | 1195 | ||
1193 | outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); | 1196 | outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); |
1194 | outw((length & 0xff) << 8 | 0x00, base); | 1197 | outw((length & 0xff) << 8 | 0x00, base); |
@@ -1196,6 +1199,7 @@ static inline void isicom_send_break(struct isi_port *port, | |||
1196 | InterruptTheCard(base); | 1199 | InterruptTheCard(base); |
1197 | 1200 | ||
1198 | unlock_card(card); | 1201 | unlock_card(card); |
1202 | return 0; | ||
1199 | } | 1203 | } |
1200 | 1204 | ||
1201 | static int isicom_tiocmget(struct tty_struct *tty, struct file *file) | 1205 | static int isicom_tiocmget(struct tty_struct *tty, struct file *file) |
@@ -1305,28 +1309,11 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, | |||
1305 | { | 1309 | { |
1306 | struct isi_port *port = tty->driver_data; | 1310 | struct isi_port *port = tty->driver_data; |
1307 | void __user *argp = (void __user *)arg; | 1311 | void __user *argp = (void __user *)arg; |
1308 | int retval; | ||
1309 | 1312 | ||
1310 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) | 1313 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) |
1311 | return -ENODEV; | 1314 | return -ENODEV; |
1312 | 1315 | ||
1313 | switch (cmd) { | 1316 | switch (cmd) { |
1314 | case TCSBRK: | ||
1315 | retval = tty_check_change(tty); | ||
1316 | if (retval) | ||
1317 | return retval; | ||
1318 | tty_wait_until_sent(tty, 0); | ||
1319 | if (!arg) | ||
1320 | isicom_send_break(port, HZ/4); | ||
1321 | return 0; | ||
1322 | |||
1323 | case TCSBRKP: | ||
1324 | retval = tty_check_change(tty); | ||
1325 | if (retval) | ||
1326 | return retval; | ||
1327 | tty_wait_until_sent(tty, 0); | ||
1328 | isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4); | ||
1329 | return 0; | ||
1330 | case TIOCGSERIAL: | 1317 | case TIOCGSERIAL: |
1331 | return isicom_get_serial_info(port, argp); | 1318 | return isicom_get_serial_info(port, argp); |
1332 | 1319 | ||
@@ -1459,6 +1446,7 @@ static const struct tty_operations isicom_ops = { | |||
1459 | .flush_buffer = isicom_flush_buffer, | 1446 | .flush_buffer = isicom_flush_buffer, |
1460 | .tiocmget = isicom_tiocmget, | 1447 | .tiocmget = isicom_tiocmget, |
1461 | .tiocmset = isicom_tiocmset, | 1448 | .tiocmset = isicom_tiocmset, |
1449 | .break_ctl = isicom_send_break, | ||
1462 | }; | 1450 | }; |
1463 | 1451 | ||
1464 | static int __devinit reset_card(struct pci_dev *pdev, | 1452 | static int __devinit reset_card(struct pci_dev *pdev, |
@@ -1832,7 +1820,7 @@ static int __init isicom_init(void) | |||
1832 | isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | | 1820 | isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | |
1833 | CLOCAL; | 1821 | CLOCAL; |
1834 | isicom_normal->flags = TTY_DRIVER_REAL_RAW | | 1822 | isicom_normal->flags = TTY_DRIVER_REAL_RAW | |
1835 | TTY_DRIVER_DYNAMIC_DEV; | 1823 | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK; |
1836 | tty_set_operations(isicom_normal, &isicom_ops); | 1824 | tty_set_operations(isicom_normal, &isicom_ops); |
1837 | 1825 | ||
1838 | retval = tty_register_driver(isicom_normal); | 1826 | retval = tty_register_driver(isicom_normal); |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 6ef1c565705c..843a2afaf204 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -598,7 +598,7 @@ static int stli_parsebrd(struct stlconf *confp, char **argp); | |||
598 | static int stli_open(struct tty_struct *tty, struct file *filp); | 598 | static int stli_open(struct tty_struct *tty, struct file *filp); |
599 | static void stli_close(struct tty_struct *tty, struct file *filp); | 599 | static void stli_close(struct tty_struct *tty, struct file *filp); |
600 | static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); | 600 | static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); |
601 | static void stli_putchar(struct tty_struct *tty, unsigned char ch); | 601 | static int stli_putchar(struct tty_struct *tty, unsigned char ch); |
602 | static void stli_flushchars(struct tty_struct *tty); | 602 | static void stli_flushchars(struct tty_struct *tty); |
603 | static int stli_writeroom(struct tty_struct *tty); | 603 | static int stli_writeroom(struct tty_struct *tty); |
604 | static int stli_charsinbuffer(struct tty_struct *tty); | 604 | static int stli_charsinbuffer(struct tty_struct *tty); |
@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty); | |||
609 | static void stli_stop(struct tty_struct *tty); | 609 | static void stli_stop(struct tty_struct *tty); |
610 | static void stli_start(struct tty_struct *tty); | 610 | static void stli_start(struct tty_struct *tty); |
611 | static void stli_flushbuffer(struct tty_struct *tty); | 611 | static void stli_flushbuffer(struct tty_struct *tty); |
612 | static void stli_breakctl(struct tty_struct *tty, int state); | 612 | static int stli_breakctl(struct tty_struct *tty, int state); |
613 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); | 613 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); |
614 | static void stli_sendxchar(struct tty_struct *tty, char ch); | 614 | static void stli_sendxchar(struct tty_struct *tty, char ch); |
615 | static void stli_hangup(struct tty_struct *tty); | 615 | static void stli_hangup(struct tty_struct *tty); |
@@ -826,7 +826,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
826 | */ | 826 | */ |
827 | portp->port.tty = tty; | 827 | portp->port.tty = tty; |
828 | tty->driver_data = portp; | 828 | tty->driver_data = portp; |
829 | portp->refcount++; | 829 | portp->port.count++; |
830 | 830 | ||
831 | wait_event_interruptible(portp->raw_wait, | 831 | wait_event_interruptible(portp->raw_wait, |
832 | !test_bit(ST_INITIALIZING, &portp->state)); | 832 | !test_bit(ST_INITIALIZING, &portp->state)); |
@@ -888,9 +888,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
888 | spin_unlock_irqrestore(&stli_lock, flags); | 888 | spin_unlock_irqrestore(&stli_lock, flags); |
889 | return; | 889 | return; |
890 | } | 890 | } |
891 | if ((tty->count == 1) && (portp->refcount != 1)) | 891 | if ((tty->count == 1) && (portp->port.count != 1)) |
892 | portp->refcount = 1; | 892 | portp->port.count = 1; |
893 | if (portp->refcount-- > 1) { | 893 | if (portp->port.count-- > 1) { |
894 | spin_unlock_irqrestore(&stli_lock, flags); | 894 | spin_unlock_irqrestore(&stli_lock, flags); |
895 | return; | 895 | return; |
896 | } | 896 | } |
@@ -925,8 +925,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
925 | clear_bit(ST_TXBUSY, &portp->state); | 925 | clear_bit(ST_TXBUSY, &portp->state); |
926 | clear_bit(ST_RXSTOP, &portp->state); | 926 | clear_bit(ST_RXSTOP, &portp->state); |
927 | set_bit(TTY_IO_ERROR, &tty->flags); | 927 | set_bit(TTY_IO_ERROR, &tty->flags); |
928 | if (tty->ldisc.flush_buffer) | 928 | tty_ldisc_flush(tty); |
929 | (tty->ldisc.flush_buffer)(tty); | ||
930 | set_bit(ST_DOFLUSHRX, &portp->state); | 929 | set_bit(ST_DOFLUSHRX, &portp->state); |
931 | stli_flushbuffer(tty); | 930 | stli_flushbuffer(tty); |
932 | 931 | ||
@@ -1202,7 +1201,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct | |||
1202 | spin_lock_irqsave(&stli_lock, flags); | 1201 | spin_lock_irqsave(&stli_lock, flags); |
1203 | portp->openwaitcnt++; | 1202 | portp->openwaitcnt++; |
1204 | if (! tty_hung_up_p(filp)) | 1203 | if (! tty_hung_up_p(filp)) |
1205 | portp->refcount--; | 1204 | portp->port.count--; |
1206 | spin_unlock_irqrestore(&stli_lock, flags); | 1205 | spin_unlock_irqrestore(&stli_lock, flags); |
1207 | 1206 | ||
1208 | for (;;) { | 1207 | for (;;) { |
@@ -1231,7 +1230,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct | |||
1231 | 1230 | ||
1232 | spin_lock_irqsave(&stli_lock, flags); | 1231 | spin_lock_irqsave(&stli_lock, flags); |
1233 | if (! tty_hung_up_p(filp)) | 1232 | if (! tty_hung_up_p(filp)) |
1234 | portp->refcount++; | 1233 | portp->port.count++; |
1235 | portp->openwaitcnt--; | 1234 | portp->openwaitcnt--; |
1236 | spin_unlock_irqrestore(&stli_lock, flags); | 1235 | spin_unlock_irqrestore(&stli_lock, flags); |
1237 | 1236 | ||
@@ -1333,7 +1332,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun | |||
1333 | * first them do the new ports. | 1332 | * first them do the new ports. |
1334 | */ | 1333 | */ |
1335 | 1334 | ||
1336 | static void stli_putchar(struct tty_struct *tty, unsigned char ch) | 1335 | static int stli_putchar(struct tty_struct *tty, unsigned char ch) |
1337 | { | 1336 | { |
1338 | if (tty != stli_txcooktty) { | 1337 | if (tty != stli_txcooktty) { |
1339 | if (stli_txcooktty != NULL) | 1338 | if (stli_txcooktty != NULL) |
@@ -1342,6 +1341,7 @@ static void stli_putchar(struct tty_struct *tty, unsigned char ch) | |||
1342 | } | 1341 | } |
1343 | 1342 | ||
1344 | stli_txcookbuf[stli_txcooksize++] = ch; | 1343 | stli_txcookbuf[stli_txcooksize++] = ch; |
1344 | return 0; | ||
1345 | } | 1345 | } |
1346 | 1346 | ||
1347 | /*****************************************************************************/ | 1347 | /*****************************************************************************/ |
@@ -1660,7 +1660,6 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm | |||
1660 | { | 1660 | { |
1661 | struct stliport *portp; | 1661 | struct stliport *portp; |
1662 | struct stlibrd *brdp; | 1662 | struct stlibrd *brdp; |
1663 | unsigned int ival; | ||
1664 | int rc; | 1663 | int rc; |
1665 | void __user *argp = (void __user *)arg; | 1664 | void __user *argp = (void __user *)arg; |
1666 | 1665 | ||
@@ -1857,7 +1856,7 @@ static void stli_hangup(struct tty_struct *tty) | |||
1857 | set_bit(TTY_IO_ERROR, &tty->flags); | 1856 | set_bit(TTY_IO_ERROR, &tty->flags); |
1858 | portp->port.tty = NULL; | 1857 | portp->port.tty = NULL; |
1859 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1858 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1860 | portp->refcount = 0; | 1859 | portp->port.count = 0; |
1861 | spin_unlock_irqrestore(&stli_lock, flags); | 1860 | spin_unlock_irqrestore(&stli_lock, flags); |
1862 | 1861 | ||
1863 | wake_up_interruptible(&portp->port.open_wait); | 1862 | wake_up_interruptible(&portp->port.open_wait); |
@@ -1909,7 +1908,7 @@ static void stli_flushbuffer(struct tty_struct *tty) | |||
1909 | 1908 | ||
1910 | /*****************************************************************************/ | 1909 | /*****************************************************************************/ |
1911 | 1910 | ||
1912 | static void stli_breakctl(struct tty_struct *tty, int state) | 1911 | static int stli_breakctl(struct tty_struct *tty, int state) |
1913 | { | 1912 | { |
1914 | struct stlibrd *brdp; | 1913 | struct stlibrd *brdp; |
1915 | struct stliport *portp; | 1914 | struct stliport *portp; |
@@ -1917,15 +1916,16 @@ static void stli_breakctl(struct tty_struct *tty, int state) | |||
1917 | 1916 | ||
1918 | portp = tty->driver_data; | 1917 | portp = tty->driver_data; |
1919 | if (portp == NULL) | 1918 | if (portp == NULL) |
1920 | return; | 1919 | return -EINVAL; |
1921 | if (portp->brdnr >= stli_nrbrds) | 1920 | if (portp->brdnr >= stli_nrbrds) |
1922 | return; | 1921 | return -EINVAL; |
1923 | brdp = stli_brds[portp->brdnr]; | 1922 | brdp = stli_brds[portp->brdnr]; |
1924 | if (brdp == NULL) | 1923 | if (brdp == NULL) |
1925 | return; | 1924 | return -EINVAL; |
1926 | 1925 | ||
1927 | arg = (state == -1) ? BREAKON : BREAKOFF; | 1926 | arg = (state == -1) ? BREAKON : BREAKOFF; |
1928 | stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); | 1927 | stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); |
1928 | return 0; | ||
1929 | } | 1929 | } |
1930 | 1930 | ||
1931 | /*****************************************************************************/ | 1931 | /*****************************************************************************/ |
@@ -4246,7 +4246,7 @@ static int stli_portcmdstats(struct stliport *portp) | |||
4246 | stli_comstats.panel = portp->panelnr; | 4246 | stli_comstats.panel = portp->panelnr; |
4247 | stli_comstats.port = portp->portnr; | 4247 | stli_comstats.port = portp->portnr; |
4248 | stli_comstats.state = portp->state; | 4248 | stli_comstats.state = portp->state; |
4249 | stli_comstats.flags = portp->port.flag; | 4249 | stli_comstats.flags = portp->port.flags; |
4250 | 4250 | ||
4251 | spin_lock_irqsave(&brd_lock, flags); | 4251 | spin_lock_irqsave(&brd_lock, flags); |
4252 | if (portp->port.tty != NULL) { | 4252 | if (portp->port.tty != NULL) { |
@@ -4599,8 +4599,9 @@ static int __init istallion_module_init(void) | |||
4599 | 4599 | ||
4600 | istallion_class = class_create(THIS_MODULE, "staliomem"); | 4600 | istallion_class = class_create(THIS_MODULE, "staliomem"); |
4601 | for (i = 0; i < 4; i++) | 4601 | for (i = 0; i < 4; i++) |
4602 | device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), | 4602 | device_create_drvdata(istallion_class, NULL, |
4603 | "staliomem%d", i); | 4603 | MKDEV(STL_SIOMEMMAJOR, i), |
4604 | NULL, "staliomem%d", i); | ||
4604 | 4605 | ||
4605 | return 0; | 4606 | return 0; |
4606 | err_deinit: | 4607 | err_deinit: |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index d9a0a53c842d..7b3a212c86b1 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -46,6 +46,8 @@ | |||
46 | 46 | ||
47 | extern void ctrl_alt_del(void); | 47 | extern void ctrl_alt_del(void); |
48 | 48 | ||
49 | #define to_handle_h(n) container_of(n, struct input_handle, h_node) | ||
50 | |||
49 | /* | 51 | /* |
50 | * Exported functions/variables | 52 | * Exported functions/variables |
51 | */ | 53 | */ |
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c deleted file mode 100644 index 1c29b20e4f4c..000000000000 --- a/drivers/char/lcd.c +++ /dev/null | |||
@@ -1,516 +0,0 @@ | |||
1 | /* | ||
2 | * LCD, LED and Button interface for Cobalt | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 1996, 1997 by Andrew Bose | ||
9 | * | ||
10 | * Linux kernel version history: | ||
11 | * March 2001: Ported from 2.0.34 by Liam Davies | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/miscdevice.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/fcntl.h> | ||
20 | #include <linux/mc146818rtc.h> | ||
21 | #include <linux/netdevice.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/delay.h> | ||
25 | |||
26 | #include <asm/io.h> | ||
27 | #include <asm/uaccess.h> | ||
28 | #include <asm/system.h> | ||
29 | |||
30 | #include "lcd.h" | ||
31 | |||
32 | static int lcd_ioctl(struct inode *inode, struct file *file, | ||
33 | unsigned int cmd, unsigned long arg); | ||
34 | |||
35 | static unsigned int lcd_present = 1; | ||
36 | |||
37 | /* used in arch/mips/cobalt/reset.c */ | ||
38 | int led_state = 0; | ||
39 | |||
40 | #if defined(CONFIG_TULIP) && 0 | ||
41 | |||
42 | #define MAX_INTERFACES 8 | ||
43 | static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES]; | ||
44 | static void *linkcheck_cookies[MAX_INTERFACES]; | ||
45 | |||
46 | int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie) | ||
47 | { | ||
48 | if (iface_num < 0 || | ||
49 | iface_num >= MAX_INTERFACES || | ||
50 | linkcheck_callbacks[iface_num] != NULL) | ||
51 | return -1; | ||
52 | linkcheck_callbacks[iface_num] = (linkcheck_func_t) func; | ||
53 | linkcheck_cookies[iface_num] = cookie; | ||
54 | return 0; | ||
55 | } | ||
56 | #endif | ||
57 | |||
58 | static int lcd_ioctl(struct inode *inode, struct file *file, | ||
59 | unsigned int cmd, unsigned long arg) | ||
60 | { | ||
61 | struct lcd_display button_display; | ||
62 | unsigned long address, a; | ||
63 | |||
64 | switch (cmd) { | ||
65 | case LCD_On: | ||
66 | udelay(150); | ||
67 | BusyCheck(); | ||
68 | LCDWriteInst(0x0F); | ||
69 | break; | ||
70 | |||
71 | case LCD_Off: | ||
72 | udelay(150); | ||
73 | BusyCheck(); | ||
74 | LCDWriteInst(0x08); | ||
75 | break; | ||
76 | |||
77 | case LCD_Reset: | ||
78 | udelay(150); | ||
79 | LCDWriteInst(0x3F); | ||
80 | udelay(150); | ||
81 | LCDWriteInst(0x3F); | ||
82 | udelay(150); | ||
83 | LCDWriteInst(0x3F); | ||
84 | udelay(150); | ||
85 | LCDWriteInst(0x3F); | ||
86 | udelay(150); | ||
87 | LCDWriteInst(0x01); | ||
88 | udelay(150); | ||
89 | LCDWriteInst(0x06); | ||
90 | break; | ||
91 | |||
92 | case LCD_Clear: | ||
93 | udelay(150); | ||
94 | BusyCheck(); | ||
95 | LCDWriteInst(0x01); | ||
96 | break; | ||
97 | |||
98 | case LCD_Cursor_Left: | ||
99 | udelay(150); | ||
100 | BusyCheck(); | ||
101 | LCDWriteInst(0x10); | ||
102 | break; | ||
103 | |||
104 | case LCD_Cursor_Right: | ||
105 | udelay(150); | ||
106 | BusyCheck(); | ||
107 | LCDWriteInst(0x14); | ||
108 | break; | ||
109 | |||
110 | case LCD_Cursor_Off: | ||
111 | udelay(150); | ||
112 | BusyCheck(); | ||
113 | LCDWriteInst(0x0C); | ||
114 | break; | ||
115 | |||
116 | case LCD_Cursor_On: | ||
117 | udelay(150); | ||
118 | BusyCheck(); | ||
119 | LCDWriteInst(0x0F); | ||
120 | break; | ||
121 | |||
122 | case LCD_Blink_Off: | ||
123 | udelay(150); | ||
124 | BusyCheck(); | ||
125 | LCDWriteInst(0x0E); | ||
126 | break; | ||
127 | |||
128 | case LCD_Get_Cursor_Pos:{ | ||
129 | struct lcd_display display; | ||
130 | |||
131 | udelay(150); | ||
132 | BusyCheck(); | ||
133 | display.cursor_address = (LCDReadInst); | ||
134 | display.cursor_address = | ||
135 | (display.cursor_address & 0x07F); | ||
136 | if (copy_to_user | ||
137 | ((struct lcd_display *) arg, &display, | ||
138 | sizeof(struct lcd_display))) | ||
139 | return -EFAULT; | ||
140 | |||
141 | break; | ||
142 | } | ||
143 | |||
144 | |||
145 | case LCD_Set_Cursor_Pos:{ | ||
146 | struct lcd_display display; | ||
147 | |||
148 | if (copy_from_user | ||
149 | (&display, (struct lcd_display *) arg, | ||
150 | sizeof(struct lcd_display))) | ||
151 | return -EFAULT; | ||
152 | |||
153 | a = (display.cursor_address | kLCD_Addr); | ||
154 | |||
155 | udelay(150); | ||
156 | BusyCheck(); | ||
157 | LCDWriteInst(a); | ||
158 | |||
159 | break; | ||
160 | } | ||
161 | |||
162 | case LCD_Get_Cursor:{ | ||
163 | struct lcd_display display; | ||
164 | |||
165 | udelay(150); | ||
166 | BusyCheck(); | ||
167 | display.character = LCDReadData; | ||
168 | |||
169 | if (copy_to_user | ||
170 | ((struct lcd_display *) arg, &display, | ||
171 | sizeof(struct lcd_display))) | ||
172 | return -EFAULT; | ||
173 | udelay(150); | ||
174 | BusyCheck(); | ||
175 | LCDWriteInst(0x10); | ||
176 | |||
177 | break; | ||
178 | } | ||
179 | |||
180 | case LCD_Set_Cursor:{ | ||
181 | struct lcd_display display; | ||
182 | |||
183 | if (copy_from_user | ||
184 | (&display, (struct lcd_display *) arg, | ||
185 | sizeof(struct lcd_display))) | ||
186 | return -EFAULT; | ||
187 | |||
188 | udelay(150); | ||
189 | BusyCheck(); | ||
190 | LCDWriteData(display.character); | ||
191 | udelay(150); | ||
192 | BusyCheck(); | ||
193 | LCDWriteInst(0x10); | ||
194 | |||
195 | break; | ||
196 | } | ||
197 | |||
198 | |||
199 | case LCD_Disp_Left: | ||
200 | udelay(150); | ||
201 | BusyCheck(); | ||
202 | LCDWriteInst(0x18); | ||
203 | break; | ||
204 | |||
205 | case LCD_Disp_Right: | ||
206 | udelay(150); | ||
207 | BusyCheck(); | ||
208 | LCDWriteInst(0x1C); | ||
209 | break; | ||
210 | |||
211 | case LCD_Home: | ||
212 | udelay(150); | ||
213 | BusyCheck(); | ||
214 | LCDWriteInst(0x02); | ||
215 | break; | ||
216 | |||
217 | case LCD_Write:{ | ||
218 | struct lcd_display display; | ||
219 | unsigned int index; | ||
220 | |||
221 | |||
222 | if (copy_from_user | ||
223 | (&display, (struct lcd_display *) arg, | ||
224 | sizeof(struct lcd_display))) | ||
225 | return -EFAULT; | ||
226 | |||
227 | udelay(150); | ||
228 | BusyCheck(); | ||
229 | LCDWriteInst(0x80); | ||
230 | udelay(150); | ||
231 | BusyCheck(); | ||
232 | |||
233 | for (index = 0; index < (display.size1); index++) { | ||
234 | udelay(150); | ||
235 | BusyCheck(); | ||
236 | LCDWriteData(display.line1[index]); | ||
237 | BusyCheck(); | ||
238 | } | ||
239 | |||
240 | udelay(150); | ||
241 | BusyCheck(); | ||
242 | LCDWriteInst(0xC0); | ||
243 | udelay(150); | ||
244 | BusyCheck(); | ||
245 | for (index = 0; index < (display.size2); index++) { | ||
246 | udelay(150); | ||
247 | BusyCheck(); | ||
248 | LCDWriteData(display.line2[index]); | ||
249 | } | ||
250 | |||
251 | break; | ||
252 | } | ||
253 | |||
254 | case LCD_Read:{ | ||
255 | struct lcd_display display; | ||
256 | |||
257 | BusyCheck(); | ||
258 | for (address = kDD_R00; address <= kDD_R01; | ||
259 | address++) { | ||
260 | a = (address | kLCD_Addr); | ||
261 | |||
262 | udelay(150); | ||
263 | BusyCheck(); | ||
264 | LCDWriteInst(a); | ||
265 | udelay(150); | ||
266 | BusyCheck(); | ||
267 | display.line1[address] = LCDReadData; | ||
268 | } | ||
269 | |||
270 | display.line1[0x27] = '\0'; | ||
271 | |||
272 | for (address = kDD_R10; address <= kDD_R11; | ||
273 | address++) { | ||
274 | a = (address | kLCD_Addr); | ||
275 | |||
276 | udelay(150); | ||
277 | BusyCheck(); | ||
278 | LCDWriteInst(a); | ||
279 | |||
280 | udelay(150); | ||
281 | BusyCheck(); | ||
282 | display.line2[address - 0x40] = | ||
283 | LCDReadData; | ||
284 | } | ||
285 | |||
286 | display.line2[0x27] = '\0'; | ||
287 | |||
288 | if (copy_to_user | ||
289 | ((struct lcd_display *) arg, &display, | ||
290 | sizeof(struct lcd_display))) | ||
291 | return -EFAULT; | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | // set all GPIO leds to led_display.leds | ||
296 | |||
297 | case LED_Set:{ | ||
298 | struct lcd_display led_display; | ||
299 | |||
300 | |||
301 | if (copy_from_user | ||
302 | (&led_display, (struct lcd_display *) arg, | ||
303 | sizeof(struct lcd_display))) | ||
304 | return -EFAULT; | ||
305 | |||
306 | led_state = led_display.leds; | ||
307 | LEDSet(led_state); | ||
308 | |||
309 | break; | ||
310 | } | ||
311 | |||
312 | |||
313 | // set only bit led_display.leds | ||
314 | |||
315 | case LED_Bit_Set:{ | ||
316 | unsigned int i; | ||
317 | int bit = 1; | ||
318 | struct lcd_display led_display; | ||
319 | |||
320 | |||
321 | if (copy_from_user | ||
322 | (&led_display, (struct lcd_display *) arg, | ||
323 | sizeof(struct lcd_display))) | ||
324 | return -EFAULT; | ||
325 | |||
326 | for (i = 0; i < (int) led_display.leds; i++) { | ||
327 | bit = 2 * bit; | ||
328 | } | ||
329 | |||
330 | led_state = led_state | bit; | ||
331 | LEDSet(led_state); | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | // clear only bit led_display.leds | ||
336 | |||
337 | case LED_Bit_Clear:{ | ||
338 | unsigned int i; | ||
339 | int bit = 1; | ||
340 | struct lcd_display led_display; | ||
341 | |||
342 | |||
343 | if (copy_from_user | ||
344 | (&led_display, (struct lcd_display *) arg, | ||
345 | sizeof(struct lcd_display))) | ||
346 | return -EFAULT; | ||
347 | |||
348 | for (i = 0; i < (int) led_display.leds; i++) { | ||
349 | bit = 2 * bit; | ||
350 | } | ||
351 | |||
352 | led_state = led_state & ~bit; | ||
353 | LEDSet(led_state); | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | |||
358 | case BUTTON_Read:{ | ||
359 | button_display.buttons = GPIRead; | ||
360 | if (copy_to_user | ||
361 | ((struct lcd_display *) arg, &button_display, | ||
362 | sizeof(struct lcd_display))) | ||
363 | return -EFAULT; | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | case LINK_Check:{ | ||
368 | button_display.buttons = | ||
369 | *((volatile unsigned long *) (0xB0100060)); | ||
370 | if (copy_to_user | ||
371 | ((struct lcd_display *) arg, &button_display, | ||
372 | sizeof(struct lcd_display))) | ||
373 | return -EFAULT; | ||
374 | break; | ||
375 | } | ||
376 | |||
377 | case LINK_Check_2:{ | ||
378 | int iface_num; | ||
379 | |||
380 | /* panel-utils should pass in the desired interface status is wanted for | ||
381 | * in "buttons" of the structure. We will set this to non-zero if the | ||
382 | * link is in fact up for the requested interface. --DaveM | ||
383 | */ | ||
384 | if (copy_from_user | ||
385 | (&button_display, (struct lcd_display *) arg, | ||
386 | sizeof(button_display))) | ||
387 | return -EFAULT; | ||
388 | iface_num = button_display.buttons; | ||
389 | #if defined(CONFIG_TULIP) && 0 | ||
390 | if (iface_num >= 0 && | ||
391 | iface_num < MAX_INTERFACES && | ||
392 | linkcheck_callbacks[iface_num] != NULL) { | ||
393 | button_display.buttons = | ||
394 | linkcheck_callbacks[iface_num] | ||
395 | (linkcheck_cookies[iface_num]); | ||
396 | } else | ||
397 | #endif | ||
398 | button_display.buttons = 0; | ||
399 | |||
400 | if (__copy_to_user | ||
401 | ((struct lcd_display *) arg, &button_display, | ||
402 | sizeof(struct lcd_display))) | ||
403 | return -EFAULT; | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | default: | ||
408 | return -EINVAL; | ||
409 | |||
410 | } | ||
411 | |||
412 | return 0; | ||
413 | |||
414 | } | ||
415 | |||
416 | static int lcd_open(struct inode *inode, struct file *file) | ||
417 | { | ||
418 | cycle_kernel_lock(); | ||
419 | |||
420 | if (!lcd_present) | ||
421 | return -ENXIO; | ||
422 | else | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | /* Only RESET or NEXT counts as button pressed */ | ||
427 | |||
428 | static inline int button_pressed(void) | ||
429 | { | ||
430 | unsigned long buttons = GPIRead; | ||
431 | |||
432 | if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) | ||
433 | || (buttons == BUTTON_Reset_B)) | ||
434 | return buttons; | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | /* LED daemon sits on this and we wake him up once a key is pressed. */ | ||
439 | |||
440 | static int lcd_waiters = 0; | ||
441 | |||
442 | static ssize_t lcd_read(struct file *file, char *buf, | ||
443 | size_t count, loff_t *ofs) | ||
444 | { | ||
445 | long buttons_now; | ||
446 | |||
447 | if (lcd_waiters > 0) | ||
448 | return -EINVAL; | ||
449 | |||
450 | lcd_waiters++; | ||
451 | while (((buttons_now = (long) button_pressed()) == 0) && | ||
452 | !(signal_pending(current))) { | ||
453 | msleep_interruptible(2000); | ||
454 | } | ||
455 | lcd_waiters--; | ||
456 | |||
457 | if (signal_pending(current)) | ||
458 | return -ERESTARTSYS; | ||
459 | return buttons_now; | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * The various file operations we support. | ||
464 | */ | ||
465 | |||
466 | static const struct file_operations lcd_fops = { | ||
467 | .read = lcd_read, | ||
468 | .ioctl = lcd_ioctl, | ||
469 | .open = lcd_open, | ||
470 | }; | ||
471 | |||
472 | static struct miscdevice lcd_dev = { | ||
473 | MISC_DYNAMIC_MINOR, | ||
474 | "lcd", | ||
475 | &lcd_fops | ||
476 | }; | ||
477 | |||
478 | static int lcd_init(void) | ||
479 | { | ||
480 | int ret; | ||
481 | unsigned long data; | ||
482 | |||
483 | pr_info("%s\n", LCD_DRIVER); | ||
484 | ret = misc_register(&lcd_dev); | ||
485 | if (ret) { | ||
486 | printk(KERN_WARNING LCD "Unable to register misc device.\n"); | ||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | /* Check region? Naaah! Just snarf it up. */ | ||
491 | /* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/ | ||
492 | |||
493 | udelay(150); | ||
494 | data = LCDReadData; | ||
495 | if ((data & 0x000000FF) == (0x00)) { | ||
496 | lcd_present = 0; | ||
497 | pr_info(LCD "LCD Not Present\n"); | ||
498 | } else { | ||
499 | lcd_present = 1; | ||
500 | WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg); | ||
501 | WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg); | ||
502 | } | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static void __exit lcd_exit(void) | ||
508 | { | ||
509 | misc_deregister(&lcd_dev); | ||
510 | } | ||
511 | |||
512 | module_init(lcd_init); | ||
513 | module_exit(lcd_exit); | ||
514 | |||
515 | MODULE_AUTHOR("Andrew Bose"); | ||
516 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h deleted file mode 100644 index 290b3ff23b03..000000000000 --- a/drivers/char/lcd.h +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | /* | ||
2 | * LED, LCD and Button panel driver for Cobalt | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 1996, 1997 by Andrew Bose | ||
9 | * | ||
10 | * Linux kernel version history: | ||
11 | * March 2001: Ported from 2.0.34 by Liam Davies | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | // function headers | ||
16 | |||
17 | #define LCD_CHARS_PER_LINE 40 | ||
18 | #define MAX_IDLE_TIME 120 | ||
19 | |||
20 | struct lcd_display { | ||
21 | unsigned buttons; | ||
22 | int size1; | ||
23 | int size2; | ||
24 | unsigned char line1[LCD_CHARS_PER_LINE]; | ||
25 | unsigned char line2[LCD_CHARS_PER_LINE]; | ||
26 | unsigned char cursor_address; | ||
27 | unsigned char character; | ||
28 | unsigned char leds; | ||
29 | unsigned char *RomImage; | ||
30 | }; | ||
31 | |||
32 | |||
33 | |||
34 | #define LCD_DRIVER "Cobalt LCD Driver v2.10" | ||
35 | |||
36 | #define LCD "lcd: " | ||
37 | |||
38 | #define kLCD_IR 0x0F000000 | ||
39 | #define kLCD_DR 0x0F000010 | ||
40 | #define kGPI 0x0D000000 | ||
41 | #define kLED 0x0C000000 | ||
42 | |||
43 | #define kDD_R00 0x00 | ||
44 | #define kDD_R01 0x27 | ||
45 | #define kDD_R10 0x40 | ||
46 | #define kDD_R11 0x67 | ||
47 | |||
48 | #define kLCD_Addr 0x00000080 | ||
49 | |||
50 | #define LCDTimeoutValue 0xfff | ||
51 | |||
52 | |||
53 | // Macros | ||
54 | |||
55 | #define LCDWriteData(x) outl((x << 24), kLCD_DR) | ||
56 | #define LCDWriteInst(x) outl((x << 24), kLCD_IR) | ||
57 | |||
58 | #define LCDReadData (inl(kLCD_DR) >> 24) | ||
59 | #define LCDReadInst (inl(kLCD_IR) >> 24) | ||
60 | |||
61 | #define GPIRead (inl(kGPI) >> 24) | ||
62 | |||
63 | #define LEDSet(x) outb((char)x, kLED) | ||
64 | |||
65 | #define WRITE_GAL(x,y) outl(y, 0x04000000 | (x)) | ||
66 | #define BusyCheck() while ((LCDReadInst & 0x80) == 0x80) | ||
67 | |||
68 | |||
69 | |||
70 | /* | ||
71 | * Function command codes for io_ctl. | ||
72 | */ | ||
73 | #define LCD_On 1 | ||
74 | #define LCD_Off 2 | ||
75 | #define LCD_Clear 3 | ||
76 | #define LCD_Reset 4 | ||
77 | #define LCD_Cursor_Left 5 | ||
78 | #define LCD_Cursor_Right 6 | ||
79 | #define LCD_Disp_Left 7 | ||
80 | #define LCD_Disp_Right 8 | ||
81 | #define LCD_Get_Cursor 9 | ||
82 | #define LCD_Set_Cursor 10 | ||
83 | #define LCD_Home 11 | ||
84 | #define LCD_Read 12 | ||
85 | #define LCD_Write 13 | ||
86 | #define LCD_Cursor_Off 14 | ||
87 | #define LCD_Cursor_On 15 | ||
88 | #define LCD_Get_Cursor_Pos 16 | ||
89 | #define LCD_Set_Cursor_Pos 17 | ||
90 | #define LCD_Blink_Off 18 | ||
91 | |||
92 | #define LED_Set 40 | ||
93 | #define LED_Bit_Set 41 | ||
94 | #define LED_Bit_Clear 42 | ||
95 | |||
96 | |||
97 | // Button defs | ||
98 | #define BUTTON_Read 50 | ||
99 | |||
100 | |||
101 | // Ethernet LINK check hackaroo | ||
102 | #define LINK_Check 90 | ||
103 | #define LINK_Check_2 91 | ||
104 | |||
105 | // Button patterns _B - single layer lcd boards | ||
106 | |||
107 | #define BUTTON_NONE 0x3F | ||
108 | #define BUTTON_NONE_B 0xFE | ||
109 | |||
110 | #define BUTTON_Left 0x3B | ||
111 | #define BUTTON_Left_B 0xFA | ||
112 | |||
113 | #define BUTTON_Right 0x37 | ||
114 | #define BUTTON_Right_B 0xDE | ||
115 | |||
116 | #define BUTTON_Up 0x2F | ||
117 | #define BUTTON_Up_B 0xF6 | ||
118 | |||
119 | #define BUTTON_Down 0x1F | ||
120 | #define BUTTON_Down_B 0xEE | ||
121 | |||
122 | #define BUTTON_Next 0x3D | ||
123 | #define BUTTON_Next_B 0x7E | ||
124 | |||
125 | #define BUTTON_Enter 0x3E | ||
126 | #define BUTTON_Enter_B 0xBE | ||
127 | |||
128 | #define BUTTON_Reset_B 0xFC | ||
129 | |||
130 | |||
131 | // debounce constants | ||
132 | |||
133 | #define BUTTON_SENSE 160000 | ||
134 | #define BUTTON_DEBOUNCE 5000 | ||
135 | |||
136 | |||
137 | // Galileo register stuff | ||
138 | |||
139 | #define kGal_DevBank2Cfg 0x1466DB33 | ||
140 | #define kGal_DevBank2PReg 0x464 | ||
141 | #define kGal_DevBank3Cfg 0x146FDFFB | ||
142 | #define kGal_DevBank3PReg 0x468 | ||
143 | |||
144 | // Network | ||
145 | |||
146 | #define kIPADDR 1 | ||
147 | #define kNETMASK 2 | ||
148 | #define kGATEWAY 3 | ||
149 | #define kDNS 4 | ||
150 | |||
151 | #define kClassA 5 | ||
152 | #define kClassB 6 | ||
153 | #define kClassC 7 | ||
154 | |||
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 71abb4c33aa2..3f2719b9f77b 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -813,7 +813,8 @@ static int lp_register(int nr, struct parport *port) | |||
813 | if (reset) | 813 | if (reset) |
814 | lp_reset(nr); | 814 | lp_reset(nr); |
815 | 815 | ||
816 | device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr); | 816 | device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, |
817 | "lp%d", nr); | ||
817 | 818 | ||
818 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, | 819 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, |
819 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); | 820 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 070e22e8ea9e..672b08e694d0 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -80,7 +80,7 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) | |||
80 | } | 80 | } |
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | #ifdef CONFIG_NONPROMISC_DEVMEM | 83 | #ifdef CONFIG_STRICT_DEVMEM |
84 | static inline int range_is_allowed(unsigned long pfn, unsigned long size) | 84 | static inline int range_is_allowed(unsigned long pfn, unsigned long size) |
85 | { | 85 | { |
86 | u64 from = ((u64)pfn) << PAGE_SHIFT; | 86 | u64 from = ((u64)pfn) << PAGE_SHIFT; |
@@ -327,7 +327,10 @@ static void mmap_mem_close(struct vm_area_struct *vma) | |||
327 | 327 | ||
328 | static struct vm_operations_struct mmap_mem_ops = { | 328 | static struct vm_operations_struct mmap_mem_ops = { |
329 | .open = mmap_mem_open, | 329 | .open = mmap_mem_open, |
330 | .close = mmap_mem_close | 330 | .close = mmap_mem_close, |
331 | #ifdef CONFIG_HAVE_IOREMAP_PROT | ||
332 | .access = generic_access_phys | ||
333 | #endif | ||
331 | }; | 334 | }; |
332 | 335 | ||
333 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 336 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) |
@@ -989,9 +992,9 @@ static int __init chr_dev_init(void) | |||
989 | 992 | ||
990 | mem_class = class_create(THIS_MODULE, "mem"); | 993 | mem_class = class_create(THIS_MODULE, "mem"); |
991 | for (i = 0; i < ARRAY_SIZE(devlist); i++) | 994 | for (i = 0; i < ARRAY_SIZE(devlist); i++) |
992 | device_create(mem_class, NULL, | 995 | device_create_drvdata(mem_class, NULL, |
993 | MKDEV(MEM_MAJOR, devlist[i].minor), | 996 | MKDEV(MEM_MAJOR, devlist[i].minor), |
994 | devlist[i].name); | 997 | NULL, devlist[i].name); |
995 | 998 | ||
996 | return 0; | 999 | return 0; |
997 | } | 1000 | } |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 6e1563c3d30a..999aa779c08a 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc) | |||
217 | misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); | 217 | misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); |
218 | dev = MKDEV(MISC_MAJOR, misc->minor); | 218 | dev = MKDEV(MISC_MAJOR, misc->minor); |
219 | 219 | ||
220 | misc->this_device = device_create(misc_class, misc->parent, dev, | 220 | misc->this_device = device_create_drvdata(misc_class, misc->parent, |
221 | "%s", misc->name); | 221 | dev, NULL, "%s", misc->name); |
222 | if (IS_ERR(misc->this_device)) { | 222 | if (IS_ERR(misc->this_device)) { |
223 | err = PTR_ERR(misc->this_device); | 223 | err = PTR_ERR(misc->this_device); |
224 | goto out; | 224 | goto out; |
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 192961fd7173..918711aa56f3 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
34 | #include <linux/math64.h> | 34 | #include <linux/math64.h> |
35 | #include <linux/smp_lock.h> | ||
35 | 36 | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <asm/sn/addrs.h> | 38 | #include <asm/sn/addrs.h> |
@@ -57,8 +58,8 @@ extern unsigned long sn_rtc_cycles_per_second; | |||
57 | 58 | ||
58 | #define rtc_time() (*RTC_COUNTER_ADDR) | 59 | #define rtc_time() (*RTC_COUNTER_ADDR) |
59 | 60 | ||
60 | static int mmtimer_ioctl(struct inode *inode, struct file *file, | 61 | static long mmtimer_ioctl(struct file *file, unsigned int cmd, |
61 | unsigned int cmd, unsigned long arg); | 62 | unsigned long arg); |
62 | static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); | 63 | static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); |
63 | 64 | ||
64 | /* | 65 | /* |
@@ -67,9 +68,9 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); | |||
67 | static unsigned long mmtimer_femtoperiod = 0; | 68 | static unsigned long mmtimer_femtoperiod = 0; |
68 | 69 | ||
69 | static const struct file_operations mmtimer_fops = { | 70 | static const struct file_operations mmtimer_fops = { |
70 | .owner = THIS_MODULE, | 71 | .owner = THIS_MODULE, |
71 | .mmap = mmtimer_mmap, | 72 | .mmap = mmtimer_mmap, |
72 | .ioctl = mmtimer_ioctl, | 73 | .unlocked_ioctl = mmtimer_ioctl, |
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* | 76 | /* |
@@ -339,7 +340,6 @@ restart: | |||
339 | 340 | ||
340 | /** | 341 | /** |
341 | * mmtimer_ioctl - ioctl interface for /dev/mmtimer | 342 | * mmtimer_ioctl - ioctl interface for /dev/mmtimer |
342 | * @inode: inode of the device | ||
343 | * @file: file structure for the device | 343 | * @file: file structure for the device |
344 | * @cmd: command to execute | 344 | * @cmd: command to execute |
345 | * @arg: optional argument to command | 345 | * @arg: optional argument to command |
@@ -365,11 +365,13 @@ restart: | |||
365 | * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it | 365 | * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it |
366 | * in the address specified by @arg. | 366 | * in the address specified by @arg. |
367 | */ | 367 | */ |
368 | static int mmtimer_ioctl(struct inode *inode, struct file *file, | 368 | static long mmtimer_ioctl(struct file *file, unsigned int cmd, |
369 | unsigned int cmd, unsigned long arg) | 369 | unsigned long arg) |
370 | { | 370 | { |
371 | int ret = 0; | 371 | int ret = 0; |
372 | 372 | ||
373 | lock_kernel(); | ||
374 | |||
373 | switch (cmd) { | 375 | switch (cmd) { |
374 | case MMTIMER_GETOFFSET: /* offset of the counter */ | 376 | case MMTIMER_GETOFFSET: /* offset of the counter */ |
375 | /* | 377 | /* |
@@ -384,15 +386,14 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file, | |||
384 | case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ | 386 | case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ |
385 | if(copy_to_user((unsigned long __user *)arg, | 387 | if(copy_to_user((unsigned long __user *)arg, |
386 | &mmtimer_femtoperiod, sizeof(unsigned long))) | 388 | &mmtimer_femtoperiod, sizeof(unsigned long))) |
387 | return -EFAULT; | 389 | ret = -EFAULT; |
388 | break; | 390 | break; |
389 | 391 | ||
390 | case MMTIMER_GETFREQ: /* frequency in Hz */ | 392 | case MMTIMER_GETFREQ: /* frequency in Hz */ |
391 | if(copy_to_user((unsigned long __user *)arg, | 393 | if(copy_to_user((unsigned long __user *)arg, |
392 | &sn_rtc_cycles_per_second, | 394 | &sn_rtc_cycles_per_second, |
393 | sizeof(unsigned long))) | 395 | sizeof(unsigned long))) |
394 | return -EFAULT; | 396 | ret = -EFAULT; |
395 | ret = 0; | ||
396 | break; | 397 | break; |
397 | 398 | ||
398 | case MMTIMER_GETBITS: /* number of bits in the clock */ | 399 | case MMTIMER_GETBITS: /* number of bits in the clock */ |
@@ -406,13 +407,13 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file, | |||
406 | case MMTIMER_GETCOUNTER: | 407 | case MMTIMER_GETCOUNTER: |
407 | if(copy_to_user((unsigned long __user *)arg, | 408 | if(copy_to_user((unsigned long __user *)arg, |
408 | RTC_COUNTER_ADDR, sizeof(unsigned long))) | 409 | RTC_COUNTER_ADDR, sizeof(unsigned long))) |
409 | return -EFAULT; | 410 | ret = -EFAULT; |
410 | break; | 411 | break; |
411 | default: | 412 | default: |
412 | ret = -ENOSYS; | 413 | ret = -ENOTTY; |
413 | break; | 414 | break; |
414 | } | 415 | } |
415 | 416 | unlock_kernel(); | |
416 | return ret; | 417 | return ret; |
417 | } | 418 | } |
418 | 419 | ||
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 2bba250ffc8e..d3d7864e0c1e 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -374,12 +374,13 @@ copy: | |||
374 | return ret; | 374 | return ret; |
375 | } | 375 | } |
376 | 376 | ||
377 | static void moxa_break_ctl(struct tty_struct *tty, int state) | 377 | static int moxa_break_ctl(struct tty_struct *tty, int state) |
378 | { | 378 | { |
379 | struct moxa_port *port = tty->driver_data; | 379 | struct moxa_port *port = tty->driver_data; |
380 | 380 | ||
381 | moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, | 381 | moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, |
382 | Magic_code); | 382 | Magic_code); |
383 | return 0; | ||
383 | } | 384 | } |
384 | 385 | ||
385 | static const struct tty_operations moxa_ops = { | 386 | static const struct tty_operations moxa_ops = { |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index fe2a95b5d3c0..30f095a8c2d4 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -193,25 +193,23 @@ mspec_close(struct vm_area_struct *vma) | |||
193 | } | 193 | } |
194 | 194 | ||
195 | /* | 195 | /* |
196 | * mspec_nopfn | 196 | * mspec_fault |
197 | * | 197 | * |
198 | * Creates a mspec page and maps it to user space. | 198 | * Creates a mspec page and maps it to user space. |
199 | */ | 199 | */ |
200 | static unsigned long | 200 | static int |
201 | mspec_nopfn(struct vm_area_struct *vma, unsigned long address) | 201 | mspec_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
202 | { | 202 | { |
203 | unsigned long paddr, maddr; | 203 | unsigned long paddr, maddr; |
204 | unsigned long pfn; | 204 | unsigned long pfn; |
205 | int index; | 205 | pgoff_t index = vmf->pgoff; |
206 | struct vma_data *vdata = vma->vm_private_data; | 206 | struct vma_data *vdata = vma->vm_private_data; |
207 | 207 | ||
208 | BUG_ON(address < vdata->vm_start || address >= vdata->vm_end); | ||
209 | index = (address - vdata->vm_start) >> PAGE_SHIFT; | ||
210 | maddr = (volatile unsigned long) vdata->maddr[index]; | 208 | maddr = (volatile unsigned long) vdata->maddr[index]; |
211 | if (maddr == 0) { | 209 | if (maddr == 0) { |
212 | maddr = uncached_alloc_page(numa_node_id(), 1); | 210 | maddr = uncached_alloc_page(numa_node_id(), 1); |
213 | if (maddr == 0) | 211 | if (maddr == 0) |
214 | return NOPFN_OOM; | 212 | return VM_FAULT_OOM; |
215 | 213 | ||
216 | spin_lock(&vdata->lock); | 214 | spin_lock(&vdata->lock); |
217 | if (vdata->maddr[index] == 0) { | 215 | if (vdata->maddr[index] == 0) { |
@@ -231,13 +229,20 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) | |||
231 | 229 | ||
232 | pfn = paddr >> PAGE_SHIFT; | 230 | pfn = paddr >> PAGE_SHIFT; |
233 | 231 | ||
234 | return pfn; | 232 | /* |
233 | * vm_insert_pfn can fail with -EBUSY, but in that case it will | ||
234 | * be because another thread has installed the pte first, so it | ||
235 | * is no problem. | ||
236 | */ | ||
237 | vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); | ||
238 | |||
239 | return VM_FAULT_NOPAGE; | ||
235 | } | 240 | } |
236 | 241 | ||
237 | static struct vm_operations_struct mspec_vm_ops = { | 242 | static struct vm_operations_struct mspec_vm_ops = { |
238 | .open = mspec_open, | 243 | .open = mspec_open, |
239 | .close = mspec_close, | 244 | .close = mspec_close, |
240 | .nopfn = mspec_nopfn | 245 | .fault = mspec_fault, |
241 | }; | 246 | }; |
242 | 247 | ||
243 | /* | 248 | /* |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 50243fcd87e8..4f8d67fed292 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0); | |||
86 | 86 | ||
87 | static int mwave_open(struct inode *inode, struct file *file); | 87 | static int mwave_open(struct inode *inode, struct file *file); |
88 | static int mwave_close(struct inode *inode, struct file *file); | 88 | static int mwave_close(struct inode *inode, struct file *file); |
89 | static int mwave_ioctl(struct inode *inode, struct file *filp, | 89 | static long mwave_ioctl(struct file *filp, unsigned int iocmd, |
90 | unsigned int iocmd, unsigned long ioarg); | 90 | unsigned long ioarg); |
91 | 91 | ||
92 | MWAVE_DEVICE_DATA mwave_s_mdd; | 92 | MWAVE_DEVICE_DATA mwave_s_mdd; |
93 | 93 | ||
@@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file) | |||
119 | return retval; | 119 | return retval; |
120 | } | 120 | } |
121 | 121 | ||
122 | static int mwave_ioctl(struct inode *inode, struct file *file, | 122 | static long mwave_ioctl(struct file *file, unsigned int iocmd, |
123 | unsigned int iocmd, unsigned long ioarg) | 123 | unsigned long ioarg) |
124 | { | 124 | { |
125 | unsigned int retval = 0; | 125 | unsigned int retval = 0; |
126 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; | 126 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; |
127 | void __user *arg = (void __user *)ioarg; | 127 | void __user *arg = (void __user *)ioarg; |
128 | 128 | ||
129 | PRINTK_5(TRACE_MWAVE, | 129 | PRINTK_4(TRACE_MWAVE, |
130 | "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n", | 130 | "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n", |
131 | inode, file, iocmd, (int) ioarg); | 131 | file, iocmd, (int) ioarg); |
132 | 132 | ||
133 | switch (iocmd) { | 133 | switch (iocmd) { |
134 | 134 | ||
@@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
136 | PRINTK_1(TRACE_MWAVE, | 136 | PRINTK_1(TRACE_MWAVE, |
137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
138 | " calling tp3780I_ResetDSP\n"); | 138 | " calling tp3780I_ResetDSP\n"); |
139 | lock_kernel(); | ||
139 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); | 140 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); |
141 | unlock_kernel(); | ||
140 | PRINTK_2(TRACE_MWAVE, | 142 | PRINTK_2(TRACE_MWAVE, |
141 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 143 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
142 | " retval %x from tp3780I_ResetDSP\n", | 144 | " retval %x from tp3780I_ResetDSP\n", |
@@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
147 | PRINTK_1(TRACE_MWAVE, | 149 | PRINTK_1(TRACE_MWAVE, |
148 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 150 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
149 | " calling tp3780I_StartDSP\n"); | 151 | " calling tp3780I_StartDSP\n"); |
152 | lock_kernel(); | ||
150 | retval = tp3780I_StartDSP(&pDrvData->rBDData); | 153 | retval = tp3780I_StartDSP(&pDrvData->rBDData); |
154 | unlock_kernel(); | ||
151 | PRINTK_2(TRACE_MWAVE, | 155 | PRINTK_2(TRACE_MWAVE, |
152 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 156 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
153 | " retval %x from tp3780I_StartDSP\n", | 157 | " retval %x from tp3780I_StartDSP\n", |
@@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
161 | "mwavedd::mwave_ioctl," | 165 | "mwavedd::mwave_ioctl," |
162 | " IOCTL_MW_DSP_ABILITIES calling" | 166 | " IOCTL_MW_DSP_ABILITIES calling" |
163 | " tp3780I_QueryAbilities\n"); | 167 | " tp3780I_QueryAbilities\n"); |
168 | lock_kernel(); | ||
164 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, | 169 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, |
165 | &rAbilities); | 170 | &rAbilities); |
171 | unlock_kernel(); | ||
166 | PRINTK_2(TRACE_MWAVE, | 172 | PRINTK_2(TRACE_MWAVE, |
167 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" | 173 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" |
168 | " retval %x from tp3780I_QueryAbilities\n", | 174 | " retval %x from tp3780I_QueryAbilities\n", |
@@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
193 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," | 199 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," |
194 | " size %lx, ioarg %lx pusBuffer %p\n", | 200 | " size %lx, ioarg %lx pusBuffer %p\n", |
195 | rReadData.ulDataLength, ioarg, pusBuffer); | 201 | rReadData.ulDataLength, ioarg, pusBuffer); |
202 | lock_kernel(); | ||
196 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 203 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
197 | iocmd, | 204 | iocmd, |
198 | pusBuffer, | 205 | pusBuffer, |
199 | rReadData.ulDataLength, | 206 | rReadData.ulDataLength, |
200 | rReadData.usDspAddress); | 207 | rReadData.usDspAddress); |
208 | unlock_kernel(); | ||
201 | } | 209 | } |
202 | break; | 210 | break; |
203 | 211 | ||
@@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
215 | " size %lx, ioarg %lx pusBuffer %p\n", | 223 | " size %lx, ioarg %lx pusBuffer %p\n", |
216 | rReadData.ulDataLength / 2, ioarg, | 224 | rReadData.ulDataLength / 2, ioarg, |
217 | pusBuffer); | 225 | pusBuffer); |
226 | lock_kernel(); | ||
218 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 227 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
219 | iocmd, pusBuffer, | 228 | iocmd, pusBuffer, |
220 | rReadData.ulDataLength / 2, | 229 | rReadData.ulDataLength / 2, |
221 | rReadData.usDspAddress); | 230 | rReadData.usDspAddress); |
231 | unlock_kernel(); | ||
222 | } | 232 | } |
223 | break; | 233 | break; |
224 | 234 | ||
@@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
236 | " size %lx, ioarg %lx pusBuffer %p\n", | 246 | " size %lx, ioarg %lx pusBuffer %p\n", |
237 | rWriteData.ulDataLength, ioarg, | 247 | rWriteData.ulDataLength, ioarg, |
238 | pusBuffer); | 248 | pusBuffer); |
249 | lock_kernel(); | ||
239 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 250 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
240 | iocmd, pusBuffer, | 251 | iocmd, pusBuffer, |
241 | rWriteData.ulDataLength, | 252 | rWriteData.ulDataLength, |
242 | rWriteData.usDspAddress); | 253 | rWriteData.usDspAddress); |
254 | unlock_kernel(); | ||
243 | } | 255 | } |
244 | break; | 256 | break; |
245 | 257 | ||
@@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
257 | " size %lx, ioarg %lx pusBuffer %p\n", | 269 | " size %lx, ioarg %lx pusBuffer %p\n", |
258 | rWriteData.ulDataLength, ioarg, | 270 | rWriteData.ulDataLength, ioarg, |
259 | pusBuffer); | 271 | pusBuffer); |
272 | lock_kernel(); | ||
260 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, | 273 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, |
261 | iocmd, pusBuffer, | 274 | iocmd, pusBuffer, |
262 | rWriteData.ulDataLength, | 275 | rWriteData.ulDataLength, |
263 | rWriteData.usDspAddress); | 276 | rWriteData.usDspAddress); |
277 | unlock_kernel(); | ||
264 | } | 278 | } |
265 | break; | 279 | break; |
266 | 280 | ||
@@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
281 | ipcnum); | 295 | ipcnum); |
282 | return -EINVAL; | 296 | return -EINVAL; |
283 | } | 297 | } |
298 | lock_kernel(); | ||
284 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; | 299 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; |
285 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; | 300 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; |
301 | unlock_kernel(); | ||
286 | 302 | ||
287 | PRINTK_2(TRACE_MWAVE, | 303 | PRINTK_2(TRACE_MWAVE, |
288 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" | 304 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" |
@@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
307 | return -EINVAL; | 323 | return -EINVAL; |
308 | } | 324 | } |
309 | 325 | ||
326 | lock_kernel(); | ||
310 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 327 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
311 | DECLARE_WAITQUEUE(wait, current); | 328 | DECLARE_WAITQUEUE(wait, current); |
312 | 329 | ||
@@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
347 | " processing\n", | 364 | " processing\n", |
348 | ipcnum); | 365 | ipcnum); |
349 | } | 366 | } |
367 | unlock_kernel(); | ||
350 | } | 368 | } |
351 | break; | 369 | break; |
352 | 370 | ||
@@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
365 | ipcnum); | 383 | ipcnum); |
366 | return -EINVAL; | 384 | return -EINVAL; |
367 | } | 385 | } |
386 | lock_kernel(); | ||
368 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 387 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
369 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; | 388 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; |
370 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { | 389 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { |
371 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); | 390 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); |
372 | } | 391 | } |
373 | } | 392 | } |
393 | unlock_kernel(); | ||
374 | } | 394 | } |
375 | break; | 395 | break; |
376 | 396 | ||
377 | default: | 397 | default: |
378 | PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" | ||
379 | " Error: Unrecognized iocmd %x\n", | ||
380 | iocmd); | ||
381 | return -ENOTTY; | 398 | return -ENOTTY; |
382 | break; | 399 | break; |
383 | } /* switch */ | 400 | } /* switch */ |
@@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = { | |||
460 | .owner = THIS_MODULE, | 477 | .owner = THIS_MODULE, |
461 | .read = mwave_read, | 478 | .read = mwave_read, |
462 | .write = mwave_write, | 479 | .write = mwave_write, |
463 | .ioctl = mwave_ioctl, | 480 | .unlocked_ioctl = mwave_ioctl, |
464 | .open = mwave_open, | 481 | .open = mwave_open, |
465 | .release = mwave_close | 482 | .release = mwave_close |
466 | }; | 483 | }; |
diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h index 8eca61e0a19c..7e0d530e2e07 100644 --- a/drivers/char/mwave/mwavedd.h +++ b/drivers/char/mwave/mwavedd.h | |||
@@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA { | |||
147 | 147 | ||
148 | } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; | 148 | } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; |
149 | 149 | ||
150 | extern MWAVE_DEVICE_DATA mwave_s_mdd; | ||
151 | |||
150 | #endif | 152 | #endif |
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index f282976daaac..c68969708068 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c | |||
@@ -57,8 +57,6 @@ | |||
57 | #include "3780i.h" | 57 | #include "3780i.h" |
58 | #include "mwavepub.h" | 58 | #include "mwavepub.h" |
59 | 59 | ||
60 | extern MWAVE_DEVICE_DATA mwave_s_mdd; | ||
61 | |||
62 | static unsigned short s_ausThinkpadIrqToField[16] = | 60 | static unsigned short s_ausThinkpadIrqToField[16] = |
63 | { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, | 61 | { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, |
64 | 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; | 62 | 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 6307e301bd26..b638403e8e9c 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox |
17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. |
18 | * - Fixed x86_64 cleanness | 18 | * - Fixed x86_64 cleanness |
19 | * - Fixed sleep with spinlock held in mxser_send_break | ||
20 | */ | 19 | */ |
21 | 20 | ||
22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
@@ -47,20 +46,14 @@ | |||
47 | 46 | ||
48 | #include "mxser.h" | 47 | #include "mxser.h" |
49 | 48 | ||
50 | #define MXSER_VERSION "2.0.3" /* 1.11 */ | 49 | #define MXSER_VERSION "2.0.4" /* 1.12 */ |
51 | #define MXSERMAJOR 174 | 50 | #define MXSERMAJOR 174 |
52 | #define MXSERCUMAJOR 175 | ||
53 | 51 | ||
54 | #define MXSER_BOARDS 4 /* Max. boards */ | 52 | #define MXSER_BOARDS 4 /* Max. boards */ |
55 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | 53 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ |
56 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) | 54 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) |
57 | #define MXSER_ISR_PASS_LIMIT 100 | 55 | #define MXSER_ISR_PASS_LIMIT 100 |
58 | 56 | ||
59 | #define MXSER_ERR_IOADDR -1 | ||
60 | #define MXSER_ERR_IRQ -2 | ||
61 | #define MXSER_ERR_IRQ_CONFLIT -3 | ||
62 | #define MXSER_ERR_VECTOR -4 | ||
63 | |||
64 | /*CheckIsMoxaMust return value*/ | 57 | /*CheckIsMoxaMust return value*/ |
65 | #define MOXA_OTHER_UART 0x00 | 58 | #define MOXA_OTHER_UART 0x00 |
66 | #define MOXA_MUST_MU150_HWID 0x01 | 59 | #define MOXA_MUST_MU150_HWID 0x01 |
@@ -71,12 +64,13 @@ | |||
71 | #define UART_MCR_AFE 0x20 | 64 | #define UART_MCR_AFE 0x20 |
72 | #define UART_LSR_SPECIAL 0x1E | 65 | #define UART_LSR_SPECIAL 0x1E |
73 | 66 | ||
67 | #define PCI_DEVICE_ID_POS104UL 0x1044 | ||
74 | #define PCI_DEVICE_ID_CB108 0x1080 | 68 | #define PCI_DEVICE_ID_CB108 0x1080 |
69 | #define PCI_DEVICE_ID_CP102UF 0x1023 | ||
75 | #define PCI_DEVICE_ID_CB114 0x1142 | 70 | #define PCI_DEVICE_ID_CB114 0x1142 |
76 | #define PCI_DEVICE_ID_CP114UL 0x1143 | 71 | #define PCI_DEVICE_ID_CP114UL 0x1143 |
77 | #define PCI_DEVICE_ID_CB134I 0x1341 | 72 | #define PCI_DEVICE_ID_CB134I 0x1341 |
78 | #define PCI_DEVICE_ID_CP138U 0x1380 | 73 | #define PCI_DEVICE_ID_CP138U 0x1380 |
79 | #define PCI_DEVICE_ID_POS104UL 0x1044 | ||
80 | 74 | ||
81 | 75 | ||
82 | #define C168_ASIC_ID 1 | 76 | #define C168_ASIC_ID 1 |
@@ -142,7 +136,8 @@ static const struct mxser_cardinfo mxser_cards[] = { | |||
142 | { "CB-134I series", 4, }, | 136 | { "CB-134I series", 4, }, |
143 | { "CP-138U series", 8, }, | 137 | { "CP-138U series", 8, }, |
144 | { "POS-104UL series", 4, }, | 138 | { "POS-104UL series", 4, }, |
145 | { "CP-114UL series", 4, } | 139 | { "CP-114UL series", 4, }, |
140 | /*30*/ { "CP-102UF series", 2, } | ||
146 | }; | 141 | }; |
147 | 142 | ||
148 | /* driver_data correspond to the lines in the structure above | 143 | /* driver_data correspond to the lines in the structure above |
@@ -172,18 +167,20 @@ static struct pci_device_id mxser_pcibrds[] = { | |||
172 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, | 167 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, |
173 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, | 168 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, |
174 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, | 169 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, |
170 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, | ||
175 | { } | 171 | { } |
176 | }; | 172 | }; |
177 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | 173 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); |
178 | 174 | ||
179 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | 175 | static unsigned long ioaddr[MXSER_BOARDS]; |
180 | static int ttymajor = MXSERMAJOR; | 176 | static int ttymajor = MXSERMAJOR; |
181 | 177 | ||
182 | /* Variables for insmod */ | 178 | /* Variables for insmod */ |
183 | 179 | ||
184 | MODULE_AUTHOR("Casper Yang"); | 180 | MODULE_AUTHOR("Casper Yang"); |
185 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | 181 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); |
186 | module_param_array(ioaddr, int, NULL, 0); | 182 | module_param_array(ioaddr, ulong, NULL, 0); |
183 | MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); | ||
187 | module_param(ttymajor, int, 0); | 184 | module_param(ttymajor, int, 0); |
188 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
189 | 186 | ||
@@ -193,7 +190,6 @@ struct mxser_log { | |||
193 | unsigned long txcnt[MXSER_PORTS]; | 190 | unsigned long txcnt[MXSER_PORTS]; |
194 | }; | 191 | }; |
195 | 192 | ||
196 | |||
197 | struct mxser_mon { | 193 | struct mxser_mon { |
198 | unsigned long rxcnt; | 194 | unsigned long rxcnt; |
199 | unsigned long txcnt; | 195 | unsigned long txcnt; |
@@ -284,19 +280,9 @@ struct mxser_mstatus { | |||
284 | int dcd; | 280 | int dcd; |
285 | }; | 281 | }; |
286 | 282 | ||
287 | static struct mxser_mstatus GMStatus[MXSER_PORTS]; | ||
288 | |||
289 | static int mxserBoardCAP[MXSER_BOARDS] = { | ||
290 | 0, 0, 0, 0 | ||
291 | /* 0x180, 0x280, 0x200, 0x320 */ | ||
292 | }; | ||
293 | |||
294 | static struct mxser_board mxser_boards[MXSER_BOARDS]; | 283 | static struct mxser_board mxser_boards[MXSER_BOARDS]; |
295 | static struct tty_driver *mxvar_sdriver; | 284 | static struct tty_driver *mxvar_sdriver; |
296 | static struct mxser_log mxvar_log; | 285 | static struct mxser_log mxvar_log; |
297 | static int mxvar_diagflag; | ||
298 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
299 | static struct mxser_mon_ext mon_data_ext; | ||
300 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | 286 | static int mxser_set_baud_method[MXSER_PORTS + 1]; |
301 | 287 | ||
302 | static void mxser_enable_must_enchance_mode(unsigned long baseio) | 288 | static void mxser_enable_must_enchance_mode(unsigned long baseio) |
@@ -540,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info) | |||
540 | 526 | ||
541 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | 527 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) |
542 | { | 528 | { |
529 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
543 | unsigned char status = 0; | 530 | unsigned char status = 0; |
544 | 531 | ||
545 | status = inb(baseaddr + UART_MSR); | 532 | status = inb(baseaddr + UART_MSR); |
@@ -1316,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty) | |||
1316 | struct mxser_port *info = tty->driver_data; | 1303 | struct mxser_port *info = tty->driver_data; |
1317 | unsigned long flags; | 1304 | unsigned long flags; |
1318 | 1305 | ||
1319 | if (info->xmit_cnt <= 0 || | 1306 | if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || |
1320 | tty->stopped || | 1307 | (tty->hw_stopped && info->type != PORT_16550A && |
1321 | !info->port.xmit_buf || | 1308 | !info->board->chip_flag)) |
1322 | (tty->hw_stopped && | ||
1323 | (info->type != PORT_16550A) && | ||
1324 | (!info->board->chip_flag) | ||
1325 | )) | ||
1326 | return; | 1309 | return; |
1327 | 1310 | ||
1328 | spin_lock_irqsave(&info->slock, flags); | 1311 | spin_lock_irqsave(&info->slock, flags); |
@@ -1340,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty) | |||
1340 | int ret; | 1323 | int ret; |
1341 | 1324 | ||
1342 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | 1325 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; |
1343 | if (ret < 0) | 1326 | return ret < 0 ? 0 : ret; |
1344 | ret = 0; | ||
1345 | return ret; | ||
1346 | } | 1327 | } |
1347 | 1328 | ||
1348 | static int mxser_chars_in_buffer(struct tty_struct *tty) | 1329 | static int mxser_chars_in_buffer(struct tty_struct *tty) |
@@ -1414,7 +1395,6 @@ static int mxser_set_serial_info(struct mxser_port *info, | |||
1414 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1395 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; |
1415 | info->port.tty->low_latency = | 1396 | info->port.tty->low_latency = |
1416 | (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1397 | (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1417 | info->port.tty->low_latency = 0; | ||
1418 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | 1398 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
1419 | (new_serial.baud_base != info->baud_base || | 1399 | (new_serial.baud_base != info->baud_base || |
1420 | new_serial.custom_divisor != | 1400 | new_serial.custom_divisor != |
@@ -1464,27 +1444,6 @@ static int mxser_get_lsr_info(struct mxser_port *info, | |||
1464 | return put_user(result, value); | 1444 | return put_user(result, value); |
1465 | } | 1445 | } |
1466 | 1446 | ||
1467 | /* | ||
1468 | * This routine sends a break character out the serial port. | ||
1469 | */ | ||
1470 | static void mxser_send_break(struct mxser_port *info, int duration) | ||
1471 | { | ||
1472 | unsigned long flags; | ||
1473 | |||
1474 | if (!info->ioaddr) | ||
1475 | return; | ||
1476 | set_current_state(TASK_INTERRUPTIBLE); | ||
1477 | spin_lock_irqsave(&info->slock, flags); | ||
1478 | outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, | ||
1479 | info->ioaddr + UART_LCR); | ||
1480 | spin_unlock_irqrestore(&info->slock, flags); | ||
1481 | schedule_timeout(duration); | ||
1482 | spin_lock_irqsave(&info->slock, flags); | ||
1483 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, | ||
1484 | info->ioaddr + UART_LCR); | ||
1485 | spin_unlock_irqrestore(&info->slock, flags); | ||
1486 | } | ||
1487 | |||
1488 | static int mxser_tiocmget(struct tty_struct *tty, struct file *file) | 1447 | static int mxser_tiocmget(struct tty_struct *tty, struct file *file) |
1489 | { | 1448 | { |
1490 | struct mxser_port *info = tty->driver_data; | 1449 | struct mxser_port *info = tty->driver_data; |
@@ -1653,6 +1612,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1653 | 1612 | ||
1654 | switch (cmd) { | 1613 | switch (cmd) { |
1655 | case MOXA_GET_MAJOR: | 1614 | case MOXA_GET_MAJOR: |
1615 | if (printk_ratelimit()) | ||
1616 | printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " | ||
1617 | "%x (GET_MAJOR), fix your userspace\n", | ||
1618 | current->comm, cmd); | ||
1656 | return put_user(ttymajor, (int __user *)argp); | 1619 | return put_user(ttymajor, (int __user *)argp); |
1657 | 1620 | ||
1658 | case MOXA_CHKPORTENABLE: | 1621 | case MOXA_CHKPORTENABLE: |
@@ -1670,62 +1633,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1670 | ret = -EFAULT; | 1633 | ret = -EFAULT; |
1671 | unlock_kernel(); | 1634 | unlock_kernel(); |
1672 | return ret; | 1635 | return ret; |
1673 | case MOXA_GETMSTATUS: | 1636 | case MOXA_GETMSTATUS: { |
1637 | struct mxser_mstatus ms, __user *msu = argp; | ||
1674 | lock_kernel(); | 1638 | lock_kernel(); |
1675 | for (i = 0; i < MXSER_BOARDS; i++) | 1639 | for (i = 0; i < MXSER_BOARDS; i++) |
1676 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1640 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
1677 | port = &mxser_boards[i].ports[j]; | 1641 | port = &mxser_boards[i].ports[j]; |
1642 | memset(&ms, 0, sizeof(ms)); | ||
1678 | 1643 | ||
1679 | GMStatus[i].ri = 0; | 1644 | if (!port->ioaddr) |
1680 | if (!port->ioaddr) { | 1645 | goto copy; |
1681 | GMStatus[i].dcd = 0; | ||
1682 | GMStatus[i].dsr = 0; | ||
1683 | GMStatus[i].cts = 0; | ||
1684 | continue; | ||
1685 | } | ||
1686 | 1646 | ||
1687 | if (!port->port.tty || !port->port.tty->termios) | 1647 | if (!port->port.tty || !port->port.tty->termios) |
1688 | GMStatus[i].cflag = | 1648 | ms.cflag = port->normal_termios.c_cflag; |
1689 | port->normal_termios.c_cflag; | ||
1690 | else | 1649 | else |
1691 | GMStatus[i].cflag = | 1650 | ms.cflag = port->port.tty->termios->c_cflag; |
1692 | port->port.tty->termios->c_cflag; | ||
1693 | 1651 | ||
1694 | status = inb(port->ioaddr + UART_MSR); | 1652 | status = inb(port->ioaddr + UART_MSR); |
1695 | if (status & 0x80 /*UART_MSR_DCD */ ) | 1653 | if (status & UART_MSR_DCD) |
1696 | GMStatus[i].dcd = 1; | 1654 | ms.dcd = 1; |
1697 | else | 1655 | if (status & UART_MSR_DSR) |
1698 | GMStatus[i].dcd = 0; | 1656 | ms.dsr = 1; |
1699 | 1657 | if (status & UART_MSR_CTS) | |
1700 | if (status & 0x20 /*UART_MSR_DSR */ ) | 1658 | ms.cts = 1; |
1701 | GMStatus[i].dsr = 1; | 1659 | copy: |
1702 | else | 1660 | if (copy_to_user(msu, &ms, sizeof(ms))) { |
1703 | GMStatus[i].dsr = 0; | 1661 | unlock_kernel(); |
1704 | 1662 | return -EFAULT; | |
1705 | 1663 | } | |
1706 | if (status & 0x10 /*UART_MSR_CTS */ ) | 1664 | msu++; |
1707 | GMStatus[i].cts = 1; | ||
1708 | else | ||
1709 | GMStatus[i].cts = 0; | ||
1710 | } | 1665 | } |
1711 | unlock_kernel(); | 1666 | unlock_kernel(); |
1712 | if (copy_to_user(argp, GMStatus, | ||
1713 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
1714 | return -EFAULT; | ||
1715 | return 0; | 1667 | return 0; |
1668 | } | ||
1716 | case MOXA_ASPP_MON_EXT: { | 1669 | case MOXA_ASPP_MON_EXT: { |
1717 | int p, shiftbit; | 1670 | struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ |
1718 | unsigned long opmode; | 1671 | unsigned int cflag, iflag, p; |
1719 | unsigned cflag, iflag; | 1672 | u8 opmode; |
1673 | |||
1674 | me = kzalloc(sizeof(*me), GFP_KERNEL); | ||
1675 | if (!me) | ||
1676 | return -ENOMEM; | ||
1720 | 1677 | ||
1721 | lock_kernel(); | 1678 | lock_kernel(); |
1722 | for (i = 0; i < MXSER_BOARDS; i++) { | 1679 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
1723 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1680 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
1681 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | ||
1682 | i = MXSER_BOARDS; | ||
1683 | break; | ||
1684 | } | ||
1724 | port = &mxser_boards[i].ports[j]; | 1685 | port = &mxser_boards[i].ports[j]; |
1725 | if (!port->ioaddr) | 1686 | if (!port->ioaddr) |
1726 | continue; | 1687 | continue; |
1727 | 1688 | ||
1728 | status = mxser_get_msr(port->ioaddr, 0, i); | 1689 | status = mxser_get_msr(port->ioaddr, 0, p); |
1729 | 1690 | ||
1730 | if (status & UART_MSR_TERI) | 1691 | if (status & UART_MSR_TERI) |
1731 | port->icount.rng++; | 1692 | port->icount.rng++; |
@@ -1737,16 +1698,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1737 | port->icount.cts++; | 1698 | port->icount.cts++; |
1738 | 1699 | ||
1739 | port->mon_data.modem_status = status; | 1700 | port->mon_data.modem_status = status; |
1740 | mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; | 1701 | me->rx_cnt[p] = port->mon_data.rxcnt; |
1741 | mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; | 1702 | me->tx_cnt[p] = port->mon_data.txcnt; |
1742 | mon_data_ext.up_rxcnt[i] = | 1703 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; |
1743 | port->mon_data.up_rxcnt; | 1704 | me->up_txcnt[p] = port->mon_data.up_txcnt; |
1744 | mon_data_ext.up_txcnt[i] = | 1705 | me->modem_status[p] = |
1745 | port->mon_data.up_txcnt; | ||
1746 | mon_data_ext.modem_status[i] = | ||
1747 | port->mon_data.modem_status; | 1706 | port->mon_data.modem_status; |
1748 | mon_data_ext.baudrate[i] = | 1707 | me->baudrate[p] = tty_get_baud_rate(port->port.tty); |
1749 | tty_get_baud_rate(port->port.tty); | ||
1750 | 1708 | ||
1751 | if (!port->port.tty || !port->port.tty->termios) { | 1709 | if (!port->port.tty || !port->port.tty->termios) { |
1752 | cflag = port->normal_termios.c_cflag; | 1710 | cflag = port->normal_termios.c_cflag; |
@@ -1756,40 +1714,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1756 | iflag = port->port.tty->termios->c_iflag; | 1714 | iflag = port->port.tty->termios->c_iflag; |
1757 | } | 1715 | } |
1758 | 1716 | ||
1759 | mon_data_ext.databits[i] = cflag & CSIZE; | 1717 | me->databits[p] = cflag & CSIZE; |
1760 | 1718 | me->stopbits[p] = cflag & CSTOPB; | |
1761 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | 1719 | me->parity[p] = cflag & (PARENB | PARODD | |
1762 | 1720 | CMSPAR); | |
1763 | mon_data_ext.parity[i] = | ||
1764 | cflag & (PARENB | PARODD | CMSPAR); | ||
1765 | |||
1766 | mon_data_ext.flowctrl[i] = 0x00; | ||
1767 | 1721 | ||
1768 | if (cflag & CRTSCTS) | 1722 | if (cflag & CRTSCTS) |
1769 | mon_data_ext.flowctrl[i] |= 0x03; | 1723 | me->flowctrl[p] |= 0x03; |
1770 | 1724 | ||
1771 | if (iflag & (IXON | IXOFF)) | 1725 | if (iflag & (IXON | IXOFF)) |
1772 | mon_data_ext.flowctrl[i] |= 0x0C; | 1726 | me->flowctrl[p] |= 0x0C; |
1773 | 1727 | ||
1774 | if (port->type == PORT_16550A) | 1728 | if (port->type == PORT_16550A) |
1775 | mon_data_ext.fifo[i] = 1; | 1729 | me->fifo[p] = 1; |
1776 | else | ||
1777 | mon_data_ext.fifo[i] = 0; | ||
1778 | 1730 | ||
1779 | p = i % 4; | 1731 | opmode = inb(port->opmode_ioaddr) >> |
1780 | shiftbit = p * 2; | 1732 | ((p % 4) * 2); |
1781 | opmode = inb(port->opmode_ioaddr) >> shiftbit; | ||
1782 | opmode &= OP_MODE_MASK; | 1733 | opmode &= OP_MODE_MASK; |
1783 | 1734 | me->iftype[p] = opmode; | |
1784 | mon_data_ext.iftype[i] = opmode; | ||
1785 | |||
1786 | } | 1735 | } |
1787 | } | 1736 | } |
1788 | unlock_kernel(); | 1737 | unlock_kernel(); |
1789 | if (copy_to_user(argp, &mon_data_ext, | 1738 | if (copy_to_user(argp, me, sizeof(*me))) |
1790 | sizeof(mon_data_ext))) | 1739 | ret = -EFAULT; |
1791 | return -EFAULT; | 1740 | kfree(me); |
1792 | return 0; | 1741 | return ret; |
1793 | } | 1742 | } |
1794 | default: | 1743 | default: |
1795 | return -ENOIOCTLCMD; | 1744 | return -ENOIOCTLCMD; |
@@ -1823,7 +1772,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1823 | { | 1772 | { |
1824 | struct mxser_port *info = tty->driver_data; | 1773 | struct mxser_port *info = tty->driver_data; |
1825 | struct async_icount cnow; | 1774 | struct async_icount cnow; |
1826 | struct serial_icounter_struct __user *p_cuser; | ||
1827 | unsigned long flags; | 1775 | unsigned long flags; |
1828 | void __user *argp = (void __user *)arg; | 1776 | void __user *argp = (void __user *)arg; |
1829 | int retval; | 1777 | int retval; |
@@ -1872,21 +1820,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1872 | return -EIO; | 1820 | return -EIO; |
1873 | 1821 | ||
1874 | switch (cmd) { | 1822 | switch (cmd) { |
1875 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
1876 | retval = tty_check_change(tty); | ||
1877 | if (retval) | ||
1878 | return retval; | ||
1879 | tty_wait_until_sent(tty, 0); | ||
1880 | if (!arg) | ||
1881 | mxser_send_break(info, HZ / 4); /* 1/4 second */ | ||
1882 | return 0; | ||
1883 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
1884 | retval = tty_check_change(tty); | ||
1885 | if (retval) | ||
1886 | return retval; | ||
1887 | tty_wait_until_sent(tty, 0); | ||
1888 | mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); | ||
1889 | return 0; | ||
1890 | case TIOCGSERIAL: | 1823 | case TIOCGSERIAL: |
1891 | lock_kernel(); | 1824 | lock_kernel(); |
1892 | retval = mxser_get_serial_info(info, argp); | 1825 | retval = mxser_get_serial_info(info, argp); |
@@ -1918,30 +1851,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1918 | * NB: both 1->0 and 0->1 transitions are counted except for | 1851 | * NB: both 1->0 and 0->1 transitions are counted except for |
1919 | * RI where only 0->1 is counted. | 1852 | * RI where only 0->1 is counted. |
1920 | */ | 1853 | */ |
1921 | case TIOCGICOUNT: | 1854 | case TIOCGICOUNT: { |
1855 | struct serial_icounter_struct icnt = { 0 }; | ||
1922 | spin_lock_irqsave(&info->slock, flags); | 1856 | spin_lock_irqsave(&info->slock, flags); |
1923 | cnow = info->icount; | 1857 | cnow = info->icount; |
1924 | spin_unlock_irqrestore(&info->slock, flags); | 1858 | spin_unlock_irqrestore(&info->slock, flags); |
1925 | p_cuser = argp; | 1859 | |
1926 | if (put_user(cnow.frame, &p_cuser->frame)) | 1860 | icnt.frame = cnow.frame; |
1927 | return -EFAULT; | 1861 | icnt.brk = cnow.brk; |
1928 | if (put_user(cnow.brk, &p_cuser->brk)) | 1862 | icnt.overrun = cnow.overrun; |
1929 | return -EFAULT; | 1863 | icnt.buf_overrun = cnow.buf_overrun; |
1930 | if (put_user(cnow.overrun, &p_cuser->overrun)) | 1864 | icnt.parity = cnow.parity; |
1931 | return -EFAULT; | 1865 | icnt.rx = cnow.rx; |
1932 | if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | 1866 | icnt.tx = cnow.tx; |
1933 | return -EFAULT; | 1867 | icnt.cts = cnow.cts; |
1934 | if (put_user(cnow.parity, &p_cuser->parity)) | 1868 | icnt.dsr = cnow.dsr; |
1935 | return -EFAULT; | 1869 | icnt.rng = cnow.rng; |
1936 | if (put_user(cnow.rx, &p_cuser->rx)) | 1870 | icnt.dcd = cnow.dcd; |
1937 | return -EFAULT; | 1871 | |
1938 | if (put_user(cnow.tx, &p_cuser->tx)) | 1872 | return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; |
1939 | return -EFAULT; | 1873 | } |
1940 | put_user(cnow.cts, &p_cuser->cts); | ||
1941 | put_user(cnow.dsr, &p_cuser->dsr); | ||
1942 | put_user(cnow.rng, &p_cuser->rng); | ||
1943 | put_user(cnow.dcd, &p_cuser->dcd); | ||
1944 | return 0; | ||
1945 | case MOXA_HighSpeedOn: | 1874 | case MOXA_HighSpeedOn: |
1946 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1875 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1947 | case MOXA_SDS_RSTICOUNTER: | 1876 | case MOXA_SDS_RSTICOUNTER: |
@@ -2219,7 +2148,7 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2219 | /* | 2148 | /* |
2220 | * mxser_rs_break() --- routine which turns the break handling on or off | 2149 | * mxser_rs_break() --- routine which turns the break handling on or off |
2221 | */ | 2150 | */ |
2222 | static void mxser_rs_break(struct tty_struct *tty, int break_state) | 2151 | static int mxser_rs_break(struct tty_struct *tty, int break_state) |
2223 | { | 2152 | { |
2224 | struct mxser_port *info = tty->driver_data; | 2153 | struct mxser_port *info = tty->driver_data; |
2225 | unsigned long flags; | 2154 | unsigned long flags; |
@@ -2232,6 +2161,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state) | |||
2232 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, | 2161 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, |
2233 | info->ioaddr + UART_LCR); | 2162 | info->ioaddr + UART_LCR); |
2234 | spin_unlock_irqrestore(&info->slock, flags); | 2163 | spin_unlock_irqrestore(&info->slock, flags); |
2164 | return 0; | ||
2235 | } | 2165 | } |
2236 | 2166 | ||
2237 | static void mxser_receive_chars(struct mxser_port *port, int *status) | 2167 | static void mxser_receive_chars(struct mxser_port *port, int *status) |
@@ -2536,7 +2466,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2536 | unsigned int i; | 2466 | unsigned int i; |
2537 | int retval; | 2467 | int retval; |
2538 | 2468 | ||
2539 | printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); | 2469 | printk(KERN_INFO "mxser: max. baud rate = %d bps\n", |
2470 | brd->ports[0].max_baud); | ||
2540 | 2471 | ||
2541 | for (i = 0; i < brd->info->nports; i++) { | 2472 | for (i = 0; i < brd->info->nports; i++) { |
2542 | info = &brd->ports[i]; | 2473 | info = &brd->ports[i]; |
@@ -2619,28 +2550,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
2619 | irq = regs[9] & 0xF000; | 2550 | irq = regs[9] & 0xF000; |
2620 | irq = irq | (irq >> 4); | 2551 | irq = irq | (irq >> 4); |
2621 | if (irq != (regs[9] & 0xFF00)) | 2552 | if (irq != (regs[9] & 0xFF00)) |
2622 | return MXSER_ERR_IRQ_CONFLIT; | 2553 | goto err_irqconflict; |
2623 | } else if (brd->info->nports == 4) { | 2554 | } else if (brd->info->nports == 4) { |
2624 | irq = regs[9] & 0xF000; | 2555 | irq = regs[9] & 0xF000; |
2625 | irq = irq | (irq >> 4); | 2556 | irq = irq | (irq >> 4); |
2626 | irq = irq | (irq >> 8); | 2557 | irq = irq | (irq >> 8); |
2627 | if (irq != regs[9]) | 2558 | if (irq != regs[9]) |
2628 | return MXSER_ERR_IRQ_CONFLIT; | 2559 | goto err_irqconflict; |
2629 | } else if (brd->info->nports == 8) { | 2560 | } else if (brd->info->nports == 8) { |
2630 | irq = regs[9] & 0xF000; | 2561 | irq = regs[9] & 0xF000; |
2631 | irq = irq | (irq >> 4); | 2562 | irq = irq | (irq >> 4); |
2632 | irq = irq | (irq >> 8); | 2563 | irq = irq | (irq >> 8); |
2633 | if ((irq != regs[9]) || (irq != regs[10])) | 2564 | if ((irq != regs[9]) || (irq != regs[10])) |
2634 | return MXSER_ERR_IRQ_CONFLIT; | 2565 | goto err_irqconflict; |
2635 | } | 2566 | } |
2636 | 2567 | ||
2637 | if (!irq) | 2568 | if (!irq) { |
2638 | return MXSER_ERR_IRQ; | 2569 | printk(KERN_ERR "mxser: interrupt number unset\n"); |
2570 | return -EIO; | ||
2571 | } | ||
2639 | brd->irq = ((int)(irq & 0xF000) >> 12); | 2572 | brd->irq = ((int)(irq & 0xF000) >> 12); |
2640 | for (i = 0; i < 8; i++) | 2573 | for (i = 0; i < 8; i++) |
2641 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; | 2574 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; |
2642 | if ((regs[12] & 0x80) == 0) | 2575 | if ((regs[12] & 0x80) == 0) { |
2643 | return MXSER_ERR_VECTOR; | 2576 | printk(KERN_ERR "mxser: invalid interrupt vector\n"); |
2577 | return -EIO; | ||
2578 | } | ||
2644 | brd->vector = (int)regs[11]; /* interrupt vector */ | 2579 | brd->vector = (int)regs[11]; /* interrupt vector */ |
2645 | if (id == 1) | 2580 | if (id == 1) |
2646 | brd->vector_mask = 0x00FF; | 2581 | brd->vector_mask = 0x00FF; |
@@ -2667,13 +2602,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
2667 | else | 2602 | else |
2668 | brd->uart_type = PORT_16450; | 2603 | brd->uart_type = PORT_16450; |
2669 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, | 2604 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, |
2670 | "mxser(IO)")) | 2605 | "mxser(IO)")) { |
2671 | return MXSER_ERR_IOADDR; | 2606 | printk(KERN_ERR "mxser: can't request ports I/O region: " |
2607 | "0x%.8lx-0x%.8lx\n", | ||
2608 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
2609 | 8 * brd->info->nports - 1); | ||
2610 | return -EIO; | ||
2611 | } | ||
2672 | if (!request_region(brd->vector, 1, "mxser(vector)")) { | 2612 | if (!request_region(brd->vector, 1, "mxser(vector)")) { |
2673 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | 2613 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2674 | return MXSER_ERR_VECTOR; | 2614 | printk(KERN_ERR "mxser: can't request interrupt vector region: " |
2615 | "0x%.8lx-0x%.8lx\n", | ||
2616 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
2617 | 8 * brd->info->nports - 1); | ||
2618 | return -EIO; | ||
2675 | } | 2619 | } |
2676 | return brd->info->nports; | 2620 | return brd->info->nports; |
2621 | |||
2622 | err_irqconflict: | ||
2623 | printk(KERN_ERR "mxser: invalid interrupt number\n"); | ||
2624 | return -EIO; | ||
2677 | } | 2625 | } |
2678 | 2626 | ||
2679 | static int __devinit mxser_probe(struct pci_dev *pdev, | 2627 | static int __devinit mxser_probe(struct pci_dev *pdev, |
@@ -2690,20 +2638,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2690 | break; | 2638 | break; |
2691 | 2639 | ||
2692 | if (i >= MXSER_BOARDS) { | 2640 | if (i >= MXSER_BOARDS) { |
2693 | printk(KERN_ERR "Too many Smartio/Industio family boards found " | 2641 | dev_err(&pdev->dev, "too many boards found (maximum %d), board " |
2694 | "(maximum %d), board not configured\n", MXSER_BOARDS); | 2642 | "not configured\n", MXSER_BOARDS); |
2695 | goto err; | 2643 | goto err; |
2696 | } | 2644 | } |
2697 | 2645 | ||
2698 | brd = &mxser_boards[i]; | 2646 | brd = &mxser_boards[i]; |
2699 | brd->idx = i * MXSER_PORTS_PER_BOARD; | 2647 | brd->idx = i * MXSER_PORTS_PER_BOARD; |
2700 | printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", | 2648 | dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", |
2701 | mxser_cards[ent->driver_data].name, | 2649 | mxser_cards[ent->driver_data].name, |
2702 | pdev->bus->number, PCI_SLOT(pdev->devfn)); | 2650 | pdev->bus->number, PCI_SLOT(pdev->devfn)); |
2703 | 2651 | ||
2704 | retval = pci_enable_device(pdev); | 2652 | retval = pci_enable_device(pdev); |
2705 | if (retval) { | 2653 | if (retval) { |
2706 | printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); | 2654 | dev_err(&pdev->dev, "PCI enable failed\n"); |
2707 | goto err; | 2655 | goto err; |
2708 | } | 2656 | } |
2709 | 2657 | ||
@@ -2805,11 +2753,8 @@ static struct pci_driver mxser_driver = { | |||
2805 | static int __init mxser_module_init(void) | 2753 | static int __init mxser_module_init(void) |
2806 | { | 2754 | { |
2807 | struct mxser_board *brd; | 2755 | struct mxser_board *brd; |
2808 | unsigned long cap; | 2756 | unsigned int b, i, m; |
2809 | unsigned int i, m, isaloop; | 2757 | int retval; |
2810 | int retval, b; | ||
2811 | |||
2812 | pr_debug("Loading module mxser ...\n"); | ||
2813 | 2758 | ||
2814 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | 2759 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); |
2815 | if (!mxvar_sdriver) | 2760 | if (!mxvar_sdriver) |
@@ -2839,74 +2784,43 @@ static int __init mxser_module_init(void) | |||
2839 | goto err_put; | 2784 | goto err_put; |
2840 | } | 2785 | } |
2841 | 2786 | ||
2842 | mxvar_diagflag = 0; | ||
2843 | |||
2844 | m = 0; | ||
2845 | /* Start finding ISA boards here */ | 2787 | /* Start finding ISA boards here */ |
2846 | for (isaloop = 0; isaloop < 2; isaloop++) | 2788 | for (m = 0, b = 0; b < MXSER_BOARDS; b++) { |
2847 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | 2789 | if (!ioaddr[b]) |
2848 | if (!isaloop) | 2790 | continue; |
2849 | cap = mxserBoardCAP[b]; /* predefined */ | 2791 | |
2850 | else | 2792 | brd = &mxser_boards[m]; |
2851 | cap = ioaddr[b]; /* module param */ | 2793 | retval = mxser_get_ISA_conf(!ioaddr[b], brd); |
2794 | if (retval <= 0) { | ||
2795 | brd->info = NULL; | ||
2796 | continue; | ||
2797 | } | ||
2852 | 2798 | ||
2853 | if (!cap) | 2799 | printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", |
2854 | continue; | 2800 | brd->info->name, ioaddr[b]); |
2855 | 2801 | ||
2856 | brd = &mxser_boards[m]; | 2802 | /* mxser_initbrd will hook ISR. */ |
2857 | retval = mxser_get_ISA_conf(cap, brd); | 2803 | if (mxser_initbrd(brd, NULL) < 0) { |
2858 | 2804 | brd->info = NULL; | |
2859 | if (retval != 0) | 2805 | continue; |
2860 | printk(KERN_INFO "Found MOXA %s board " | 2806 | } |
2861 | "(CAP=0x%x)\n", | ||
2862 | brd->info->name, ioaddr[b]); | ||
2863 | |||
2864 | if (retval <= 0) { | ||
2865 | if (retval == MXSER_ERR_IRQ) | ||
2866 | printk(KERN_ERR "Invalid interrupt " | ||
2867 | "number, board not " | ||
2868 | "configured\n"); | ||
2869 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
2870 | printk(KERN_ERR "Invalid interrupt " | ||
2871 | "number, board not " | ||
2872 | "configured\n"); | ||
2873 | else if (retval == MXSER_ERR_VECTOR) | ||
2874 | printk(KERN_ERR "Invalid interrupt " | ||
2875 | "vector, board not " | ||
2876 | "configured\n"); | ||
2877 | else if (retval == MXSER_ERR_IOADDR) | ||
2878 | printk(KERN_ERR "Invalid I/O address, " | ||
2879 | "board not configured\n"); | ||
2880 | |||
2881 | brd->info = NULL; | ||
2882 | continue; | ||
2883 | } | ||
2884 | |||
2885 | /* mxser_initbrd will hook ISR. */ | ||
2886 | if (mxser_initbrd(brd, NULL) < 0) { | ||
2887 | brd->info = NULL; | ||
2888 | continue; | ||
2889 | } | ||
2890 | 2807 | ||
2891 | brd->idx = m * MXSER_PORTS_PER_BOARD; | 2808 | brd->idx = m * MXSER_PORTS_PER_BOARD; |
2892 | for (i = 0; i < brd->info->nports; i++) | 2809 | for (i = 0; i < brd->info->nports; i++) |
2893 | tty_register_device(mxvar_sdriver, brd->idx + i, | 2810 | tty_register_device(mxvar_sdriver, brd->idx + i, NULL); |
2894 | NULL); | ||
2895 | 2811 | ||
2896 | m++; | 2812 | m++; |
2897 | } | 2813 | } |
2898 | 2814 | ||
2899 | retval = pci_register_driver(&mxser_driver); | 2815 | retval = pci_register_driver(&mxser_driver); |
2900 | if (retval) { | 2816 | if (retval) { |
2901 | printk(KERN_ERR "Can't register pci driver\n"); | 2817 | printk(KERN_ERR "mxser: can't register pci driver\n"); |
2902 | if (!m) { | 2818 | if (!m) { |
2903 | retval = -ENODEV; | 2819 | retval = -ENODEV; |
2904 | goto err_unr; | 2820 | goto err_unr; |
2905 | } /* else: we have some ISA cards under control */ | 2821 | } /* else: we have some ISA cards under control */ |
2906 | } | 2822 | } |
2907 | 2823 | ||
2908 | pr_debug("Done.\n"); | ||
2909 | |||
2910 | return 0; | 2824 | return 0; |
2911 | err_unr: | 2825 | err_unr: |
2912 | tty_unregister_driver(mxvar_sdriver); | 2826 | tty_unregister_driver(mxvar_sdriver); |
@@ -2919,8 +2833,6 @@ static void __exit mxser_module_exit(void) | |||
2919 | { | 2833 | { |
2920 | unsigned int i, j; | 2834 | unsigned int i, j; |
2921 | 2835 | ||
2922 | pr_debug("Unloading module mxser ...\n"); | ||
2923 | |||
2924 | pci_unregister_driver(&mxser_driver); | 2836 | pci_unregister_driver(&mxser_driver); |
2925 | 2837 | ||
2926 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ | 2838 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ |
@@ -2934,8 +2846,6 @@ static void __exit mxser_module_exit(void) | |||
2934 | for (i = 0; i < MXSER_BOARDS; i++) | 2846 | for (i = 0; i < MXSER_BOARDS; i++) |
2935 | if (mxser_boards[i].info != NULL) | 2847 | if (mxser_boards[i].info != NULL) |
2936 | mxser_release_res(&mxser_boards[i], NULL, 1); | 2848 | mxser_release_res(&mxser_boards[i], NULL, 1); |
2937 | |||
2938 | pr_debug("Done.\n"); | ||
2939 | } | 2849 | } |
2940 | 2850 | ||
2941 | module_init(mxser_module_init); | 2851 | module_init(mxser_module_init); |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index ed4e03333ab4..69ec6399c714 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -677,6 +677,10 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
677 | /* Allocate transmit buffer */ | 677 | /* Allocate transmit buffer */ |
678 | /* sleep until transmit buffer available */ | 678 | /* sleep until transmit buffer available */ |
679 | while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { | 679 | while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { |
680 | if (file->f_flags & O_NONBLOCK) { | ||
681 | error = -EAGAIN; | ||
682 | break; | ||
683 | } | ||
680 | schedule(); | 684 | schedule(); |
681 | 685 | ||
682 | n_hdlc = tty2n_hdlc (tty); | 686 | n_hdlc = tty2n_hdlc (tty); |
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index a22662b6a1a5..39f6357e3b5d 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c | |||
@@ -107,7 +107,6 @@ | |||
107 | #include <linux/init.h> | 107 | #include <linux/init.h> |
108 | #include <linux/proc_fs.h> | 108 | #include <linux/proc_fs.h> |
109 | #include <linux/spinlock.h> | 109 | #include <linux/spinlock.h> |
110 | #include <linux/smp_lock.h> | ||
111 | 110 | ||
112 | #include <asm/io.h> | 111 | #include <asm/io.h> |
113 | #include <asm/uaccess.h> | 112 | #include <asm/uaccess.h> |
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index ba012c2bdf7a..006be92ee3f3 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 | |||
122 | static ssize_t flash_read(struct file *file, char __user *buf, size_t size, | 122 | static ssize_t flash_read(struct file *file, char __user *buf, size_t size, |
123 | loff_t *ppos) | 123 | loff_t *ppos) |
124 | { | 124 | { |
125 | unsigned long p = *ppos; | 125 | ssize_t ret; |
126 | unsigned int count = size; | ||
127 | int ret = 0; | ||
128 | 126 | ||
129 | if (flashdebug) | 127 | if (flashdebug) |
130 | printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " | 128 | printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, " |
131 | "buffer=%p, count=0x%X.\n", p, buf, count); | 129 | "buffer=%p, count=0x%zx.\n", *ppos, buf, size); |
132 | 130 | /* | |
133 | if (count) | 131 | * We now lock against reads and writes. --rmk |
134 | ret = -ENXIO; | 132 | */ |
133 | if (mutex_lock_interruptible(&nwflash_mutex)) | ||
134 | return -ERESTARTSYS; | ||
135 | 135 | ||
136 | if (p < gbFlashSize) { | 136 | ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize); |
137 | if (count > gbFlashSize - p) | 137 | mutex_unlock(&nwflash_mutex); |
138 | count = gbFlashSize - p; | ||
139 | 138 | ||
140 | /* | ||
141 | * We now lock against reads and writes. --rmk | ||
142 | */ | ||
143 | if (mutex_lock_interruptible(&nwflash_mutex)) | ||
144 | return -ERESTARTSYS; | ||
145 | |||
146 | ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); | ||
147 | if (ret == 0) { | ||
148 | ret = count; | ||
149 | *ppos += count; | ||
150 | } else | ||
151 | ret = -EFAULT; | ||
152 | mutex_unlock(&nwflash_mutex); | ||
153 | } | ||
154 | return ret; | 139 | return ret; |
155 | } | 140 | } |
156 | 141 | ||
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e4a4fbd37d7a..f070ae7bd91a 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -1896,7 +1896,7 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
1896 | return ret; | 1896 | return ret; |
1897 | } | 1897 | } |
1898 | 1898 | ||
1899 | device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i); | 1899 | device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); |
1900 | 1900 | ||
1901 | return 0; | 1901 | return 0; |
1902 | } | 1902 | } |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 6181f8a9b0bd..0b5934bef7a4 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -653,7 +653,8 @@ static int reader_probe(struct pcmcia_device *link) | |||
653 | return ret; | 653 | return ret; |
654 | } | 654 | } |
655 | 655 | ||
656 | device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i); | 656 | device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL, |
657 | "cmx%d", i); | ||
657 | 658 | ||
658 | return 0; | 659 | return 0; |
659 | } | 660 | } |
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 929101ecbae2..4c1820cad712 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c | |||
@@ -30,11 +30,11 @@ | |||
30 | static void ipw_send_setup_packet(struct ipw_hardware *hw); | 30 | static void ipw_send_setup_packet(struct ipw_hardware *hw); |
31 | static void handle_received_SETUP_packet(struct ipw_hardware *ipw, | 31 | static void handle_received_SETUP_packet(struct ipw_hardware *ipw, |
32 | unsigned int address, | 32 | unsigned int address, |
33 | unsigned char *data, int len, | 33 | const unsigned char *data, int len, |
34 | int is_last); | 34 | int is_last); |
35 | static void ipwireless_setup_timer(unsigned long data); | 35 | static void ipwireless_setup_timer(unsigned long data); |
36 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, | 36 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, |
37 | unsigned int channel_idx, unsigned char *data, int len); | 37 | unsigned int channel_idx, const unsigned char *data, int len); |
38 | 38 | ||
39 | /*#define TIMING_DIAGNOSTICS*/ | 39 | /*#define TIMING_DIAGNOSTICS*/ |
40 | 40 | ||
@@ -79,8 +79,7 @@ static void report_timing(void) | |||
79 | timing_stats.last_report_time = jiffies; | 79 | timing_stats.last_report_time = jiffies; |
80 | if (!first) | 80 | if (!first) |
81 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 81 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
82 | ": %u us elapsed - read %lu bytes in %u us, " | 82 | ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", |
83 | "wrote %lu bytes in %u us\n", | ||
84 | jiffies_to_usecs(since), | 83 | jiffies_to_usecs(since), |
85 | timing_stats.read_bytes, | 84 | timing_stats.read_bytes, |
86 | jiffies_to_usecs(timing_stats.read_time), | 85 | jiffies_to_usecs(timing_stats.read_time), |
@@ -133,29 +132,17 @@ enum { | |||
133 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 | 132 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 |
134 | 133 | ||
135 | struct nl_first_packet_header { | 134 | struct nl_first_packet_header { |
136 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
137 | unsigned char packet_rank:2; | ||
138 | unsigned char address:3; | ||
139 | unsigned char protocol:3; | ||
140 | #else | ||
141 | unsigned char protocol:3; | 135 | unsigned char protocol:3; |
142 | unsigned char address:3; | 136 | unsigned char address:3; |
143 | unsigned char packet_rank:2; | 137 | unsigned char packet_rank:2; |
144 | #endif | ||
145 | unsigned char length_lsb; | 138 | unsigned char length_lsb; |
146 | unsigned char length_msb; | 139 | unsigned char length_msb; |
147 | }; | 140 | }; |
148 | 141 | ||
149 | struct nl_packet_header { | 142 | struct nl_packet_header { |
150 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
151 | unsigned char packet_rank:2; | ||
152 | unsigned char address:3; | ||
153 | unsigned char protocol:3; | ||
154 | #else | ||
155 | unsigned char protocol:3; | 143 | unsigned char protocol:3; |
156 | unsigned char address:3; | 144 | unsigned char address:3; |
157 | unsigned char packet_rank:2; | 145 | unsigned char packet_rank:2; |
158 | #endif | ||
159 | }; | 146 | }; |
160 | 147 | ||
161 | /* Value of 'packet_rank' above */ | 148 | /* Value of 'packet_rank' above */ |
@@ -227,15 +214,12 @@ struct MEMINFREG { | |||
227 | unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ | 214 | unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ |
228 | }; | 215 | }; |
229 | 216 | ||
230 | #define IODMADPR 0x00 /* DMA Data Port Register (R/W) */ | ||
231 | |||
232 | #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) | 217 | #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) |
233 | 218 | ||
234 | #define MEMTX_TX 0x0001 | 219 | #define MEMTX_TX 0x0001 |
235 | #define MEMRX_RX 0x0001 | 220 | #define MEMRX_RX 0x0001 |
236 | #define MEMRX_RX_DONE 0x0001 | 221 | #define MEMRX_RX_DONE 0x0001 |
237 | #define MEMRX_PCINTACKK 0x0001 | 222 | #define MEMRX_PCINTACKK 0x0001 |
238 | #define MEMRX_MEMSPURIOUSINT 0x0001 | ||
239 | 223 | ||
240 | #define NL_NUM_OF_PRIORITIES 3 | 224 | #define NL_NUM_OF_PRIORITIES 3 |
241 | #define NL_NUM_OF_PROTOCOLS 3 | 225 | #define NL_NUM_OF_PROTOCOLS 3 |
@@ -245,7 +229,7 @@ struct ipw_hardware { | |||
245 | unsigned int base_port; | 229 | unsigned int base_port; |
246 | short hw_version; | 230 | short hw_version; |
247 | unsigned short ll_mtu; | 231 | unsigned short ll_mtu; |
248 | spinlock_t spinlock; | 232 | spinlock_t lock; |
249 | 233 | ||
250 | int initializing; | 234 | int initializing; |
251 | int init_loops; | 235 | int init_loops; |
@@ -386,26 +370,52 @@ static void dump_data_bytes(const char *type, const unsigned char *data, | |||
386 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); | 370 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); |
387 | } | 371 | } |
388 | 372 | ||
389 | static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | 373 | static void swap_packet_bitfield_to_le(unsigned char *data) |
374 | { | ||
375 | #ifdef __BIG_ENDIAN_BITFIELD | ||
376 | unsigned char tmp = *data, ret = 0; | ||
377 | |||
378 | /* | ||
379 | * transform bits from aa.bbb.ccc to ccc.bbb.aa | ||
380 | */ | ||
381 | ret |= tmp & 0xc0 >> 6; | ||
382 | ret |= tmp & 0x38 >> 1; | ||
383 | ret |= tmp & 0x07 << 5; | ||
384 | *data = ret & 0xff; | ||
385 | #endif | ||
386 | } | ||
387 | |||
388 | static void swap_packet_bitfield_from_le(unsigned char *data) | ||
389 | { | ||
390 | #ifdef __BIG_ENDIAN_BITFIELD | ||
391 | unsigned char tmp = *data, ret = 0; | ||
392 | |||
393 | /* | ||
394 | * transform bits from ccc.bbb.aa to aa.bbb.ccc | ||
395 | */ | ||
396 | ret |= tmp & 0xe0 >> 5; | ||
397 | ret |= tmp & 0x1c << 1; | ||
398 | ret |= tmp & 0x03 << 6; | ||
399 | *data = ret & 0xff; | ||
400 | #endif | ||
401 | } | ||
402 | |||
403 | static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, | ||
390 | unsigned length) | 404 | unsigned length) |
391 | { | 405 | { |
392 | int i; | 406 | unsigned i; |
393 | unsigned long flags; | 407 | unsigned long flags; |
394 | 408 | ||
395 | start_timing(); | 409 | start_timing(); |
396 | 410 | BUG_ON(length > hw->ll_mtu); | |
397 | if (length == 0) | ||
398 | return 0; | ||
399 | |||
400 | if (length > hw->ll_mtu) | ||
401 | return -1; | ||
402 | 411 | ||
403 | if (ipwireless_debug) | 412 | if (ipwireless_debug) |
404 | dump_data_bytes("send", data, length); | 413 | dump_data_bytes("send", data, length); |
405 | 414 | ||
406 | spin_lock_irqsave(&hw->spinlock, flags); | 415 | spin_lock_irqsave(&hw->lock, flags); |
407 | 416 | ||
408 | hw->tx_ready = 0; | 417 | hw->tx_ready = 0; |
418 | swap_packet_bitfield_to_le(data); | ||
409 | 419 | ||
410 | if (hw->hw_version == HW_VERSION_1) { | 420 | if (hw->hw_version == HW_VERSION_1) { |
411 | outw((unsigned short) length, hw->base_port + IODWR); | 421 | 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, | |||
414 | unsigned short d = data[i]; | 424 | unsigned short d = data[i]; |
415 | __le16 raw_data; | 425 | __le16 raw_data; |
416 | 426 | ||
417 | if (likely(i + 1 < length)) | 427 | if (i + 1 < length) |
418 | d |= data[i + 1] << 8; | 428 | d |= data[i + 1] << 8; |
419 | raw_data = cpu_to_le16(d); | 429 | raw_data = cpu_to_le16(d); |
420 | outw(raw_data, hw->base_port + IODWR); | 430 | outw(raw_data, hw->base_port + IODWR); |
@@ -422,32 +432,30 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | |||
422 | 432 | ||
423 | outw(DCR_TXDONE, hw->base_port + IODCR); | 433 | outw(DCR_TXDONE, hw->base_port + IODCR); |
424 | } else if (hw->hw_version == HW_VERSION_2) { | 434 | } else if (hw->hw_version == HW_VERSION_2) { |
425 | outw((unsigned short) length, hw->base_port + IODMADPR); | 435 | outw((unsigned short) length, hw->base_port); |
426 | 436 | ||
427 | for (i = 0; i < length; i += 2) { | 437 | for (i = 0; i < length; i += 2) { |
428 | unsigned short d = data[i]; | 438 | unsigned short d = data[i]; |
429 | __le16 raw_data; | 439 | __le16 raw_data; |
430 | 440 | ||
431 | if ((i + 1 < length)) | 441 | if (i + 1 < length) |
432 | d |= data[i + 1] << 8; | 442 | d |= data[i + 1] << 8; |
433 | raw_data = cpu_to_le16(d); | 443 | raw_data = cpu_to_le16(d); |
434 | outw(raw_data, hw->base_port + IODMADPR); | 444 | outw(raw_data, hw->base_port); |
435 | } | 445 | } |
436 | while ((i & 3) != 2) { | 446 | while ((i & 3) != 2) { |
437 | outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR); | 447 | outw((unsigned short) 0xDEAD, hw->base_port); |
438 | i += 2; | 448 | i += 2; |
439 | } | 449 | } |
440 | writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); | 450 | writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); |
441 | } | 451 | } |
442 | 452 | ||
443 | spin_unlock_irqrestore(&hw->spinlock, flags); | 453 | spin_unlock_irqrestore(&hw->lock, flags); |
444 | 454 | ||
445 | end_write_timing(length); | 455 | end_write_timing(length); |
446 | |||
447 | return 0; | ||
448 | } | 456 | } |
449 | 457 | ||
450 | static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | 458 | static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) |
451 | { | 459 | { |
452 | unsigned short fragment_data_len; | 460 | unsigned short fragment_data_len; |
453 | unsigned short data_left = packet->length - packet->offset; | 461 | 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) | |||
462 | if (data_left < fragment_data_len) | 470 | if (data_left < fragment_data_len) |
463 | fragment_data_len = data_left; | 471 | fragment_data_len = data_left; |
464 | 472 | ||
473 | /* | ||
474 | * hdr_first is now in machine bitfield order, which will be swapped | ||
475 | * to le just before it goes to hw | ||
476 | */ | ||
465 | pkt.hdr_first.protocol = packet->protocol; | 477 | pkt.hdr_first.protocol = packet->protocol; |
466 | pkt.hdr_first.address = packet->dest_addr; | 478 | pkt.hdr_first.address = packet->dest_addr; |
467 | pkt.hdr_first.packet_rank = 0; | 479 | pkt.hdr_first.packet_rank = 0; |
@@ -493,25 +505,23 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | |||
493 | */ | 505 | */ |
494 | unsigned long flags; | 506 | unsigned long flags; |
495 | 507 | ||
496 | spin_lock_irqsave(&hw->spinlock, flags); | 508 | spin_lock_irqsave(&hw->lock, flags); |
497 | list_add(&packet->queue, &hw->tx_queue[0]); | 509 | list_add(&packet->queue, &hw->tx_queue[0]); |
498 | hw->tx_queued++; | 510 | hw->tx_queued++; |
499 | spin_unlock_irqrestore(&hw->spinlock, flags); | 511 | spin_unlock_irqrestore(&hw->lock, flags); |
500 | } else { | 512 | } else { |
501 | if (packet->packet_callback) | 513 | if (packet->packet_callback) |
502 | packet->packet_callback(packet->callback_data, | 514 | packet->packet_callback(packet->callback_data, |
503 | packet->length); | 515 | packet->length); |
504 | kfree(packet); | 516 | kfree(packet); |
505 | } | 517 | } |
506 | |||
507 | return 0; | ||
508 | } | 518 | } |
509 | 519 | ||
510 | static void ipw_setup_hardware(struct ipw_hardware *hw) | 520 | static void ipw_setup_hardware(struct ipw_hardware *hw) |
511 | { | 521 | { |
512 | unsigned long flags; | 522 | unsigned long flags; |
513 | 523 | ||
514 | spin_lock_irqsave(&hw->spinlock, flags); | 524 | spin_lock_irqsave(&hw->lock, flags); |
515 | if (hw->hw_version == HW_VERSION_1) { | 525 | if (hw->hw_version == HW_VERSION_1) { |
516 | /* Reset RX FIFO */ | 526 | /* Reset RX FIFO */ |
517 | outw(DCR_RXRESET, hw->base_port + IODCR); | 527 | outw(DCR_RXRESET, hw->base_port + IODCR); |
@@ -530,7 +540,7 @@ static void ipw_setup_hardware(struct ipw_hardware *hw) | |||
530 | csr |= 1; | 540 | csr |= 1; |
531 | writew(csr, &hw->memregs_CCR->reg_config_and_status); | 541 | writew(csr, &hw->memregs_CCR->reg_config_and_status); |
532 | } | 542 | } |
533 | spin_unlock_irqrestore(&hw->spinlock, flags); | 543 | spin_unlock_irqrestore(&hw->lock, flags); |
534 | } | 544 | } |
535 | 545 | ||
536 | /* | 546 | /* |
@@ -549,28 +559,23 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, | |||
549 | if (!packet) { | 559 | if (!packet) { |
550 | unsigned long flags; | 560 | unsigned long flags; |
551 | 561 | ||
552 | /* | 562 | spin_lock_irqsave(&hw->lock, flags); |
553 | * If this is the first fragment, then we will need to fetch a | ||
554 | * packet to put it in. | ||
555 | */ | ||
556 | spin_lock_irqsave(&hw->spinlock, flags); | ||
557 | /* If we have one in our pool, then pull it out. */ | ||
558 | if (!list_empty(&hw->rx_pool)) { | 563 | if (!list_empty(&hw->rx_pool)) { |
559 | packet = list_first_entry(&hw->rx_pool, | 564 | packet = list_first_entry(&hw->rx_pool, |
560 | struct ipw_rx_packet, queue); | 565 | struct ipw_rx_packet, queue); |
561 | list_del(&packet->queue); | ||
562 | hw->rx_pool_size--; | 566 | hw->rx_pool_size--; |
563 | spin_unlock_irqrestore(&hw->spinlock, flags); | 567 | spin_unlock_irqrestore(&hw->lock, flags); |
568 | list_del(&packet->queue); | ||
564 | } else { | 569 | } else { |
565 | /* Otherwise allocate a new one. */ | 570 | const int min_capacity = |
566 | static int min_capacity = 256; | 571 | ipwireless_ppp_mru(hw->network) + 2; |
567 | int new_capacity; | 572 | int new_capacity; |
568 | 573 | ||
569 | spin_unlock_irqrestore(&hw->spinlock, flags); | 574 | spin_unlock_irqrestore(&hw->lock, flags); |
570 | new_capacity = | 575 | new_capacity = |
571 | minimum_free_space > min_capacity | 576 | (minimum_free_space > min_capacity |
572 | ? minimum_free_space | 577 | ? minimum_free_space |
573 | : min_capacity; | 578 | : min_capacity); |
574 | packet = kmalloc(sizeof(struct ipw_rx_packet) | 579 | packet = kmalloc(sizeof(struct ipw_rx_packet) |
575 | + new_capacity, GFP_ATOMIC); | 580 | + new_capacity, GFP_ATOMIC); |
576 | if (!packet) | 581 | if (!packet) |
@@ -580,10 +585,6 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, | |||
580 | packet->length = 0; | 585 | packet->length = 0; |
581 | } | 586 | } |
582 | 587 | ||
583 | /* | ||
584 | * If this packet does not have sufficient capacity for the data we | ||
585 | * want to add, then make it bigger. | ||
586 | */ | ||
587 | if (packet->length + minimum_free_space > packet->capacity) { | 588 | if (packet->length + minimum_free_space > packet->capacity) { |
588 | struct ipw_rx_packet *old_packet = packet; | 589 | struct ipw_rx_packet *old_packet = packet; |
589 | 590 | ||
@@ -610,13 +611,15 @@ static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) | |||
610 | kfree(packet); | 611 | kfree(packet); |
611 | else { | 612 | else { |
612 | hw->rx_pool_size++; | 613 | hw->rx_pool_size++; |
613 | list_add_tail(&packet->queue, &hw->rx_pool); | 614 | list_add(&packet->queue, &hw->rx_pool); |
614 | } | 615 | } |
615 | } | 616 | } |
616 | 617 | ||
617 | static void queue_received_packet(struct ipw_hardware *hw, | 618 | static void queue_received_packet(struct ipw_hardware *hw, |
618 | unsigned int protocol, unsigned int address, | 619 | unsigned int protocol, |
619 | unsigned char *data, int length, int is_last) | 620 | unsigned int address, |
621 | const unsigned char *data, int length, | ||
622 | int is_last) | ||
620 | { | 623 | { |
621 | unsigned int channel_idx = address - 1; | 624 | unsigned int channel_idx = address - 1; |
622 | struct ipw_rx_packet *packet = NULL; | 625 | struct ipw_rx_packet *packet = NULL; |
@@ -658,9 +661,9 @@ static void queue_received_packet(struct ipw_hardware *hw, | |||
658 | packet = *assem; | 661 | packet = *assem; |
659 | *assem = NULL; | 662 | *assem = NULL; |
660 | /* Count queued DATA bytes only */ | 663 | /* Count queued DATA bytes only */ |
661 | spin_lock_irqsave(&hw->spinlock, flags); | 664 | spin_lock_irqsave(&hw->lock, flags); |
662 | hw->rx_bytes_queued += packet->length; | 665 | hw->rx_bytes_queued += packet->length; |
663 | spin_unlock_irqrestore(&hw->spinlock, flags); | 666 | spin_unlock_irqrestore(&hw->lock, flags); |
664 | } | 667 | } |
665 | } else { | 668 | } else { |
666 | /* If it's a CTRL packet, don't assemble, just queue it. */ | 669 | /* 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, | |||
682 | * network layer. | 685 | * network layer. |
683 | */ | 686 | */ |
684 | if (packet) { | 687 | if (packet) { |
685 | spin_lock_irqsave(&hw->spinlock, flags); | 688 | spin_lock_irqsave(&hw->lock, flags); |
686 | list_add_tail(&packet->queue, &hw->rx_queue); | 689 | list_add_tail(&packet->queue, &hw->rx_queue); |
687 | /* Block reception of incoming packets if queue is full. */ | 690 | /* Block reception of incoming packets if queue is full. */ |
688 | hw->blocking_rx = | 691 | hw->blocking_rx = |
689 | hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; | 692 | (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); |
690 | 693 | ||
691 | spin_unlock_irqrestore(&hw->spinlock, flags); | 694 | spin_unlock_irqrestore(&hw->lock, flags); |
692 | schedule_work(&hw->work_rx); | 695 | schedule_work(&hw->work_rx); |
693 | } | 696 | } |
694 | } | 697 | } |
@@ -702,7 +705,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
702 | container_of(work_rx, struct ipw_hardware, work_rx); | 705 | container_of(work_rx, struct ipw_hardware, work_rx); |
703 | unsigned long flags; | 706 | unsigned long flags; |
704 | 707 | ||
705 | spin_lock_irqsave(&hw->spinlock, flags); | 708 | spin_lock_irqsave(&hw->lock, flags); |
706 | while (!list_empty(&hw->rx_queue)) { | 709 | while (!list_empty(&hw->rx_queue)) { |
707 | struct ipw_rx_packet *packet = | 710 | struct ipw_rx_packet *packet = |
708 | list_first_entry(&hw->rx_queue, | 711 | list_first_entry(&hw->rx_queue, |
@@ -720,7 +723,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
720 | if (packet->protocol == TL_PROTOCOLID_COM_DATA) { | 723 | if (packet->protocol == TL_PROTOCOLID_COM_DATA) { |
721 | if (hw->network != NULL) { | 724 | if (hw->network != NULL) { |
722 | /* If the network hasn't been disconnected. */ | 725 | /* If the network hasn't been disconnected. */ |
723 | spin_unlock_irqrestore(&hw->spinlock, flags); | 726 | spin_unlock_irqrestore(&hw->lock, flags); |
724 | /* | 727 | /* |
725 | * This must run unlocked due to tty processing | 728 | * This must run unlocked due to tty processing |
726 | * and mutex locking | 729 | * and mutex locking |
@@ -731,7 +734,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
731 | (unsigned char *)packet | 734 | (unsigned char *)packet |
732 | + sizeof(struct ipw_rx_packet), | 735 | + sizeof(struct ipw_rx_packet), |
733 | packet->length); | 736 | packet->length); |
734 | spin_lock_irqsave(&hw->spinlock, flags); | 737 | spin_lock_irqsave(&hw->lock, flags); |
735 | } | 738 | } |
736 | /* Count queued DATA bytes only */ | 739 | /* Count queued DATA bytes only */ |
737 | hw->rx_bytes_queued -= packet->length; | 740 | hw->rx_bytes_queued -= packet->length; |
@@ -755,15 +758,15 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
755 | if (hw->shutting_down) | 758 | if (hw->shutting_down) |
756 | break; | 759 | break; |
757 | } | 760 | } |
758 | spin_unlock_irqrestore(&hw->spinlock, flags); | 761 | spin_unlock_irqrestore(&hw->lock, flags); |
759 | } | 762 | } |
760 | 763 | ||
761 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, | 764 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, |
762 | unsigned int channel_idx, | 765 | unsigned int channel_idx, |
763 | unsigned char *data, int len) | 766 | const unsigned char *data, int len) |
764 | { | 767 | { |
765 | struct ipw_control_packet_body *body = | 768 | const struct ipw_control_packet_body *body = |
766 | (struct ipw_control_packet_body *) data; | 769 | (const struct ipw_control_packet_body *) data; |
767 | unsigned int changed_mask; | 770 | unsigned int changed_mask; |
768 | 771 | ||
769 | if (len != sizeof(struct ipw_control_packet_body)) { | 772 | if (len != sizeof(struct ipw_control_packet_body)) { |
@@ -805,13 +808,13 @@ static void handle_received_CTRL_packet(struct ipw_hardware *hw, | |||
805 | } | 808 | } |
806 | 809 | ||
807 | static void handle_received_packet(struct ipw_hardware *hw, | 810 | static void handle_received_packet(struct ipw_hardware *hw, |
808 | union nl_packet *packet, | 811 | const union nl_packet *packet, |
809 | unsigned short len) | 812 | unsigned short len) |
810 | { | 813 | { |
811 | unsigned int protocol = packet->hdr.protocol; | 814 | unsigned int protocol = packet->hdr.protocol; |
812 | unsigned int address = packet->hdr.address; | 815 | unsigned int address = packet->hdr.address; |
813 | unsigned int header_length; | 816 | unsigned int header_length; |
814 | unsigned char *data; | 817 | const unsigned char *data; |
815 | unsigned int data_len; | 818 | unsigned int data_len; |
816 | int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; | 819 | int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; |
817 | 820 | ||
@@ -850,7 +853,7 @@ static void acknowledge_data_read(struct ipw_hardware *hw) | |||
850 | static void do_receive_packet(struct ipw_hardware *hw) | 853 | static void do_receive_packet(struct ipw_hardware *hw) |
851 | { | 854 | { |
852 | unsigned len; | 855 | unsigned len; |
853 | unsigned int i; | 856 | unsigned i; |
854 | unsigned char pkt[LL_MTU_MAX]; | 857 | unsigned char pkt[LL_MTU_MAX]; |
855 | 858 | ||
856 | start_timing(); | 859 | start_timing(); |
@@ -859,8 +862,7 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
859 | len = inw(hw->base_port + IODRR); | 862 | len = inw(hw->base_port + IODRR); |
860 | if (len > hw->ll_mtu) { | 863 | if (len > hw->ll_mtu) { |
861 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 864 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
862 | ": received a packet of %u bytes - " | 865 | ": received a packet of %u bytes - longer than the MTU!\n", len); |
863 | "longer than the MTU!\n", len); | ||
864 | outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); | 866 | outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); |
865 | return; | 867 | return; |
866 | } | 868 | } |
@@ -873,18 +875,17 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
873 | pkt[i + 1] = (unsigned char) (data >> 8); | 875 | pkt[i + 1] = (unsigned char) (data >> 8); |
874 | } | 876 | } |
875 | } else { | 877 | } else { |
876 | len = inw(hw->base_port + IODMADPR); | 878 | len = inw(hw->base_port); |
877 | if (len > hw->ll_mtu) { | 879 | if (len > hw->ll_mtu) { |
878 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 880 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
879 | ": received a packet of %u bytes - " | 881 | ": received a packet of %u bytes - longer than the MTU!\n", len); |
880 | "longer than the MTU!\n", len); | ||
881 | writew(MEMRX_PCINTACKK, | 882 | writew(MEMRX_PCINTACKK, |
882 | &hw->memory_info_regs->memreg_pc_interrupt_ack); | 883 | &hw->memory_info_regs->memreg_pc_interrupt_ack); |
883 | return; | 884 | return; |
884 | } | 885 | } |
885 | 886 | ||
886 | for (i = 0; i < len; i += 2) { | 887 | for (i = 0; i < len; i += 2) { |
887 | __le16 raw_data = inw(hw->base_port + IODMADPR); | 888 | __le16 raw_data = inw(hw->base_port); |
888 | unsigned short data = le16_to_cpu(raw_data); | 889 | unsigned short data = le16_to_cpu(raw_data); |
889 | 890 | ||
890 | pkt[i] = (unsigned char) data; | 891 | pkt[i] = (unsigned char) data; |
@@ -892,13 +893,15 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
892 | } | 893 | } |
893 | 894 | ||
894 | while ((i & 3) != 2) { | 895 | while ((i & 3) != 2) { |
895 | inw(hw->base_port + IODMADPR); | 896 | inw(hw->base_port); |
896 | i += 2; | 897 | i += 2; |
897 | } | 898 | } |
898 | } | 899 | } |
899 | 900 | ||
900 | acknowledge_data_read(hw); | 901 | acknowledge_data_read(hw); |
901 | 902 | ||
903 | swap_packet_bitfield_from_le(pkt); | ||
904 | |||
902 | if (ipwireless_debug) | 905 | if (ipwireless_debug) |
903 | dump_data_bytes("recv", pkt, len); | 906 | dump_data_bytes("recv", pkt, len); |
904 | 907 | ||
@@ -916,8 +919,7 @@ static int get_current_packet_priority(struct ipw_hardware *hw) | |||
916 | * until setup is complete. | 919 | * until setup is complete. |
917 | */ | 920 | */ |
918 | return (hw->to_setup || hw->initializing | 921 | return (hw->to_setup || hw->initializing |
919 | ? PRIO_SETUP + 1 : | 922 | ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); |
920 | NL_NUM_OF_PRIORITIES); | ||
921 | } | 923 | } |
922 | 924 | ||
923 | /* | 925 | /* |
@@ -928,17 +930,17 @@ static int get_packets_from_hw(struct ipw_hardware *hw) | |||
928 | int received = 0; | 930 | int received = 0; |
929 | unsigned long flags; | 931 | unsigned long flags; |
930 | 932 | ||
931 | spin_lock_irqsave(&hw->spinlock, flags); | 933 | spin_lock_irqsave(&hw->lock, flags); |
932 | while (hw->rx_ready && !hw->blocking_rx) { | 934 | while (hw->rx_ready && !hw->blocking_rx) { |
933 | received = 1; | 935 | received = 1; |
934 | hw->rx_ready--; | 936 | hw->rx_ready--; |
935 | spin_unlock_irqrestore(&hw->spinlock, flags); | 937 | spin_unlock_irqrestore(&hw->lock, flags); |
936 | 938 | ||
937 | do_receive_packet(hw); | 939 | do_receive_packet(hw); |
938 | 940 | ||
939 | spin_lock_irqsave(&hw->spinlock, flags); | 941 | spin_lock_irqsave(&hw->lock, flags); |
940 | } | 942 | } |
941 | spin_unlock_irqrestore(&hw->spinlock, flags); | 943 | spin_unlock_irqrestore(&hw->lock, flags); |
942 | 944 | ||
943 | return received; | 945 | return received; |
944 | } | 946 | } |
@@ -954,7 +956,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
954 | int more_to_send = 0; | 956 | int more_to_send = 0; |
955 | unsigned long flags; | 957 | unsigned long flags; |
956 | 958 | ||
957 | spin_lock_irqsave(&hw->spinlock, flags); | 959 | spin_lock_irqsave(&hw->lock, flags); |
958 | if (hw->tx_queued && hw->tx_ready) { | 960 | if (hw->tx_queued && hw->tx_ready) { |
959 | int priority; | 961 | int priority; |
960 | struct ipw_tx_packet *packet = NULL; | 962 | struct ipw_tx_packet *packet = NULL; |
@@ -975,17 +977,17 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
975 | } | 977 | } |
976 | if (!packet) { | 978 | if (!packet) { |
977 | hw->tx_queued = 0; | 979 | hw->tx_queued = 0; |
978 | spin_unlock_irqrestore(&hw->spinlock, flags); | 980 | spin_unlock_irqrestore(&hw->lock, flags); |
979 | return 0; | 981 | return 0; |
980 | } | 982 | } |
981 | 983 | ||
982 | spin_unlock_irqrestore(&hw->spinlock, flags); | 984 | spin_unlock_irqrestore(&hw->lock, flags); |
983 | 985 | ||
984 | /* Send */ | 986 | /* Send */ |
985 | do_send_packet(hw, packet); | 987 | do_send_packet(hw, packet); |
986 | 988 | ||
987 | /* Check if more to send */ | 989 | /* Check if more to send */ |
988 | spin_lock_irqsave(&hw->spinlock, flags); | 990 | spin_lock_irqsave(&hw->lock, flags); |
989 | for (priority = 0; priority < priority_limit; priority++) | 991 | for (priority = 0; priority < priority_limit; priority++) |
990 | if (!list_empty(&hw->tx_queue[priority])) { | 992 | if (!list_empty(&hw->tx_queue[priority])) { |
991 | more_to_send = 1; | 993 | more_to_send = 1; |
@@ -995,7 +997,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
995 | if (!more_to_send) | 997 | if (!more_to_send) |
996 | hw->tx_queued = 0; | 998 | hw->tx_queued = 0; |
997 | } | 999 | } |
998 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1000 | spin_unlock_irqrestore(&hw->lock, flags); |
999 | 1001 | ||
1000 | return more_to_send; | 1002 | return more_to_send; |
1001 | } | 1003 | } |
@@ -1008,9 +1010,9 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
1008 | struct ipw_hardware *hw = (struct ipw_hardware *) hw_; | 1010 | struct ipw_hardware *hw = (struct ipw_hardware *) hw_; |
1009 | unsigned long flags; | 1011 | unsigned long flags; |
1010 | 1012 | ||
1011 | spin_lock_irqsave(&hw->spinlock, flags); | 1013 | spin_lock_irqsave(&hw->lock, flags); |
1012 | if (hw->shutting_down) { | 1014 | if (hw->shutting_down) { |
1013 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1015 | spin_unlock_irqrestore(&hw->lock, flags); |
1014 | return; | 1016 | return; |
1015 | } | 1017 | } |
1016 | 1018 | ||
@@ -1019,7 +1021,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
1019 | * Initial setup data sent to hardware | 1021 | * Initial setup data sent to hardware |
1020 | */ | 1022 | */ |
1021 | hw->to_setup = 2; | 1023 | hw->to_setup = 2; |
1022 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1024 | spin_unlock_irqrestore(&hw->lock, flags); |
1023 | 1025 | ||
1024 | ipw_setup_hardware(hw); | 1026 | ipw_setup_hardware(hw); |
1025 | ipw_send_setup_packet(hw); | 1027 | ipw_send_setup_packet(hw); |
@@ -1030,7 +1032,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
1030 | int priority_limit = get_current_packet_priority(hw); | 1032 | int priority_limit = get_current_packet_priority(hw); |
1031 | int again; | 1033 | int again; |
1032 | 1034 | ||
1033 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1035 | spin_unlock_irqrestore(&hw->lock, flags); |
1034 | 1036 | ||
1035 | do { | 1037 | do { |
1036 | again = send_pending_packet(hw, priority_limit); | 1038 | again = send_pending_packet(hw, priority_limit); |
@@ -1068,16 +1070,16 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, | |||
1068 | /* Transmit complete. */ | 1070 | /* Transmit complete. */ |
1069 | if (irqn & IR_TXINTR) { | 1071 | if (irqn & IR_TXINTR) { |
1070 | ack |= IR_TXINTR; | 1072 | ack |= IR_TXINTR; |
1071 | spin_lock_irqsave(&hw->spinlock, flags); | 1073 | spin_lock_irqsave(&hw->lock, flags); |
1072 | hw->tx_ready = 1; | 1074 | hw->tx_ready = 1; |
1073 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1075 | spin_unlock_irqrestore(&hw->lock, flags); |
1074 | } | 1076 | } |
1075 | /* Received data */ | 1077 | /* Received data */ |
1076 | if (irqn & IR_RXINTR) { | 1078 | if (irqn & IR_RXINTR) { |
1077 | ack |= IR_RXINTR; | 1079 | ack |= IR_RXINTR; |
1078 | spin_lock_irqsave(&hw->spinlock, flags); | 1080 | spin_lock_irqsave(&hw->lock, flags); |
1079 | hw->rx_ready++; | 1081 | hw->rx_ready++; |
1080 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1082 | spin_unlock_irqrestore(&hw->lock, flags); |
1081 | } | 1083 | } |
1082 | if (ack != 0) { | 1084 | if (ack != 0) { |
1083 | outw(ack, hw->base_port + IOIR); | 1085 | outw(ack, hw->base_port + IOIR); |
@@ -1128,9 +1130,8 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1128 | } else { | 1130 | } else { |
1129 | return IRQ_NONE; | 1131 | return IRQ_NONE; |
1130 | } | 1132 | } |
1131 | } else { | 1133 | } else |
1132 | return IRQ_NONE; | 1134 | return IRQ_NONE; |
1133 | } | ||
1134 | } | 1135 | } |
1135 | 1136 | ||
1136 | /* | 1137 | /* |
@@ -1149,9 +1150,9 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1149 | if (hw->serial_number_detected) { | 1150 | if (hw->serial_number_detected) { |
1150 | if (memtx_serial != hw->last_memtx_serial) { | 1151 | if (memtx_serial != hw->last_memtx_serial) { |
1151 | hw->last_memtx_serial = memtx_serial; | 1152 | hw->last_memtx_serial = memtx_serial; |
1152 | spin_lock_irqsave(&hw->spinlock, flags); | 1153 | spin_lock_irqsave(&hw->lock, flags); |
1153 | hw->rx_ready++; | 1154 | hw->rx_ready++; |
1154 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1155 | spin_unlock_irqrestore(&hw->lock, flags); |
1155 | rx = 1; | 1156 | rx = 1; |
1156 | } else | 1157 | } else |
1157 | /* Ignore 'Timer Recovery' duplicates. */ | 1158 | /* Ignore 'Timer Recovery' duplicates. */ |
@@ -1166,18 +1167,18 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1166 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME | 1167 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME |
1167 | ": memreg_tx serial num detected\n"); | 1168 | ": memreg_tx serial num detected\n"); |
1168 | 1169 | ||
1169 | spin_lock_irqsave(&hw->spinlock, flags); | 1170 | spin_lock_irqsave(&hw->lock, flags); |
1170 | hw->rx_ready++; | 1171 | hw->rx_ready++; |
1171 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1172 | spin_unlock_irqrestore(&hw->lock, flags); |
1172 | } | 1173 | } |
1173 | rx = 1; | 1174 | rx = 1; |
1174 | } | 1175 | } |
1175 | } | 1176 | } |
1176 | if (memrxdone & MEMRX_RX_DONE) { | 1177 | if (memrxdone & MEMRX_RX_DONE) { |
1177 | writew(0, &hw->memory_info_regs->memreg_rx_done); | 1178 | writew(0, &hw->memory_info_regs->memreg_rx_done); |
1178 | spin_lock_irqsave(&hw->spinlock, flags); | 1179 | spin_lock_irqsave(&hw->lock, flags); |
1179 | hw->tx_ready = 1; | 1180 | hw->tx_ready = 1; |
1180 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1181 | spin_unlock_irqrestore(&hw->lock, flags); |
1181 | tx = 1; | 1182 | tx = 1; |
1182 | } | 1183 | } |
1183 | if (tx) | 1184 | if (tx) |
@@ -1195,8 +1196,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1195 | ": spurious interrupt - new_tx mode\n"); | 1196 | ": spurious interrupt - new_tx mode\n"); |
1196 | else { | 1197 | else { |
1197 | printk(KERN_WARNING IPWIRELESS_PCCARD_NAME | 1198 | printk(KERN_WARNING IPWIRELESS_PCCARD_NAME |
1198 | ": no valid memreg_tx value - " | 1199 | ": no valid memreg_tx value - switching to the old memreg_tx\n"); |
1199 | "switching to the old memreg_tx\n"); | ||
1200 | hw->memreg_tx = | 1200 | hw->memreg_tx = |
1201 | &hw->memory_info_regs->memreg_tx_old; | 1201 | &hw->memory_info_regs->memreg_tx_old; |
1202 | try_mem_tx_old = 1; | 1202 | try_mem_tx_old = 1; |
@@ -1211,7 +1211,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1211 | return IRQ_HANDLED; | 1211 | return IRQ_HANDLED; |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 1214 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id) |
1215 | { | 1215 | { |
1216 | struct ipw_hardware *hw = dev_id; | 1216 | struct ipw_hardware *hw = dev_id; |
1217 | 1217 | ||
@@ -1226,9 +1226,9 @@ static void flush_packets_to_hw(struct ipw_hardware *hw) | |||
1226 | int priority_limit; | 1226 | int priority_limit; |
1227 | unsigned long flags; | 1227 | unsigned long flags; |
1228 | 1228 | ||
1229 | spin_lock_irqsave(&hw->spinlock, flags); | 1229 | spin_lock_irqsave(&hw->lock, flags); |
1230 | priority_limit = get_current_packet_priority(hw); | 1230 | priority_limit = get_current_packet_priority(hw); |
1231 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1231 | spin_unlock_irqrestore(&hw->lock, flags); |
1232 | 1232 | ||
1233 | while (send_pending_packet(hw, priority_limit)); | 1233 | while (send_pending_packet(hw, priority_limit)); |
1234 | } | 1234 | } |
@@ -1238,10 +1238,10 @@ static void send_packet(struct ipw_hardware *hw, int priority, | |||
1238 | { | 1238 | { |
1239 | unsigned long flags; | 1239 | unsigned long flags; |
1240 | 1240 | ||
1241 | spin_lock_irqsave(&hw->spinlock, flags); | 1241 | spin_lock_irqsave(&hw->lock, flags); |
1242 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); | 1242 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); |
1243 | hw->tx_queued++; | 1243 | hw->tx_queued++; |
1244 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1244 | spin_unlock_irqrestore(&hw->lock, flags); |
1245 | 1245 | ||
1246 | flush_packets_to_hw(hw); | 1246 | flush_packets_to_hw(hw); |
1247 | } | 1247 | } |
@@ -1291,21 +1291,20 @@ static void *alloc_ctrl_packet(int header_size, | |||
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, | 1293 | int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, |
1294 | unsigned char *data, unsigned int length, | 1294 | const unsigned char *data, unsigned int length, |
1295 | void (*callback) (void *cb, unsigned int length), | 1295 | void (*callback) (void *cb, unsigned int length), |
1296 | void *callback_data) | 1296 | void *callback_data) |
1297 | { | 1297 | { |
1298 | struct ipw_tx_packet *packet; | 1298 | struct ipw_tx_packet *packet; |
1299 | 1299 | ||
1300 | packet = alloc_data_packet(length, | 1300 | packet = alloc_data_packet(length, (channel_idx + 1), |
1301 | (unsigned char) (channel_idx + 1), | 1301 | TL_PROTOCOLID_COM_DATA); |
1302 | TL_PROTOCOLID_COM_DATA); | ||
1303 | if (!packet) | 1302 | if (!packet) |
1304 | return -ENOMEM; | 1303 | return -ENOMEM; |
1305 | packet->packet_callback = callback; | 1304 | packet->packet_callback = callback; |
1306 | packet->callback_data = callback_data; | 1305 | packet->callback_data = callback_data; |
1307 | memcpy((unsigned char *) packet + | 1306 | memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, |
1308 | sizeof(struct ipw_tx_packet), data, length); | 1307 | length); |
1309 | 1308 | ||
1310 | send_packet(hw, PRIO_DATA, packet); | 1309 | send_packet(hw, PRIO_DATA, packet); |
1311 | return 0; | 1310 | return 0; |
@@ -1321,12 +1320,11 @@ static int set_control_line(struct ipw_hardware *hw, int prio, | |||
1321 | protocolid = TL_PROTOCOLID_SETUP; | 1320 | protocolid = TL_PROTOCOLID_SETUP; |
1322 | 1321 | ||
1323 | packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), | 1322 | packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), |
1324 | (unsigned char) (channel_idx + 1), | 1323 | (channel_idx + 1), protocolid, line); |
1325 | protocolid, line); | ||
1326 | if (!packet) | 1324 | if (!packet) |
1327 | return -ENOMEM; | 1325 | return -ENOMEM; |
1328 | packet->header.length = sizeof(struct ipw_control_packet_body); | 1326 | packet->header.length = sizeof(struct ipw_control_packet_body); |
1329 | packet->body.value = (unsigned char) (state == 0 ? 0 : 1); | 1327 | packet->body.value = (state == 0 ? 0 : 1); |
1330 | send_packet(hw, prio, &packet->header); | 1328 | send_packet(hw, prio, &packet->header); |
1331 | return 0; | 1329 | return 0; |
1332 | } | 1330 | } |
@@ -1504,8 +1502,7 @@ static void handle_setup_get_version_rsp(struct ipw_hardware *hw, | |||
1504 | if (vers_no == TL_SETUP_VERSION) | 1502 | if (vers_no == TL_SETUP_VERSION) |
1505 | __handle_setup_get_version_rsp(hw); | 1503 | __handle_setup_get_version_rsp(hw); |
1506 | else | 1504 | else |
1507 | printk(KERN_ERR | 1505 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME |
1508 | IPWIRELESS_PCCARD_NAME | ||
1509 | ": invalid hardware version no %u\n", | 1506 | ": invalid hardware version no %u\n", |
1510 | (unsigned int) vers_no); | 1507 | (unsigned int) vers_no); |
1511 | } | 1508 | } |
@@ -1528,10 +1525,10 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw) | |||
1528 | 1525 | ||
1529 | static void handle_received_SETUP_packet(struct ipw_hardware *hw, | 1526 | static void handle_received_SETUP_packet(struct ipw_hardware *hw, |
1530 | unsigned int address, | 1527 | unsigned int address, |
1531 | unsigned char *data, int len, | 1528 | const unsigned char *data, int len, |
1532 | int is_last) | 1529 | int is_last) |
1533 | { | 1530 | { |
1534 | union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data; | 1531 | const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; |
1535 | 1532 | ||
1536 | if (address != ADDR_SETUP_PROT) { | 1533 | if (address != ADDR_SETUP_PROT) { |
1537 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 1534 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
@@ -1629,7 +1626,7 @@ struct ipw_hardware *ipwireless_hardware_create(void) | |||
1629 | 1626 | ||
1630 | INIT_LIST_HEAD(&hw->rx_queue); | 1627 | INIT_LIST_HEAD(&hw->rx_queue); |
1631 | INIT_LIST_HEAD(&hw->rx_pool); | 1628 | INIT_LIST_HEAD(&hw->rx_pool); |
1632 | spin_lock_init(&hw->spinlock); | 1629 | spin_lock_init(&hw->lock); |
1633 | tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); | 1630 | tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); |
1634 | INIT_WORK(&hw->work_rx, ipw_receive_data_work); | 1631 | INIT_WORK(&hw->work_rx, ipw_receive_data_work); |
1635 | setup_timer(&hw->setup_timer, ipwireless_setup_timer, | 1632 | setup_timer(&hw->setup_timer, ipwireless_setup_timer, |
@@ -1651,8 +1648,8 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw, | |||
1651 | enable_irq(hw->irq); | 1648 | enable_irq(hw->irq); |
1652 | } | 1649 | } |
1653 | hw->base_port = base_port; | 1650 | hw->base_port = base_port; |
1654 | hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1; | 1651 | hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); |
1655 | hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2; | 1652 | hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); |
1656 | hw->memregs_CCR = (struct MEMCCR __iomem *) | 1653 | hw->memregs_CCR = (struct MEMCCR __iomem *) |
1657 | ((unsigned short __iomem *) attr_memory + 0x200); | 1654 | ((unsigned short __iomem *) attr_memory + 0x200); |
1658 | hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; | 1655 | hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; |
@@ -1695,10 +1692,10 @@ static void ipwireless_setup_timer(unsigned long data) | |||
1695 | if (is_card_present(hw)) { | 1692 | if (is_card_present(hw)) { |
1696 | unsigned long flags; | 1693 | unsigned long flags; |
1697 | 1694 | ||
1698 | spin_lock_irqsave(&hw->spinlock, flags); | 1695 | spin_lock_irqsave(&hw->lock, flags); |
1699 | hw->to_setup = 1; | 1696 | hw->to_setup = 1; |
1700 | hw->tx_ready = 1; | 1697 | hw->tx_ready = 1; |
1701 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1698 | spin_unlock_irqrestore(&hw->lock, flags); |
1702 | tasklet_schedule(&hw->tasklet); | 1699 | tasklet_schedule(&hw->tasklet); |
1703 | } | 1700 | } |
1704 | 1701 | ||
diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h index 19ce5eb266b1..90a8590e43b0 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.h +++ b/drivers/char/pcmcia/ipwireless/hardware.h | |||
@@ -34,14 +34,14 @@ struct ipw_network; | |||
34 | 34 | ||
35 | struct ipw_hardware *ipwireless_hardware_create(void); | 35 | struct ipw_hardware *ipwireless_hardware_create(void); |
36 | void ipwireless_hardware_free(struct ipw_hardware *hw); | 36 | void ipwireless_hardware_free(struct ipw_hardware *hw); |
37 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 37 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id); |
38 | int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, | 38 | int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, |
39 | int state); | 39 | int state); |
40 | int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, | 40 | int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, |
41 | int state); | 41 | int state); |
42 | int ipwireless_send_packet(struct ipw_hardware *hw, | 42 | int ipwireless_send_packet(struct ipw_hardware *hw, |
43 | unsigned int channel_idx, | 43 | unsigned int channel_idx, |
44 | unsigned char *data, | 44 | const unsigned char *data, |
45 | unsigned int length, | 45 | unsigned int length, |
46 | void (*packet_sent_callback) (void *cb, | 46 | void (*packet_sent_callback) (void *cb, |
47 | unsigned int length), | 47 | unsigned int length), |
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index cc7dcea2d283..5eca7a99afe6 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); | |||
49 | /* Debug mode: more verbose, print sent/recv bytes */ | 49 | /* Debug mode: more verbose, print sent/recv bytes */ |
50 | int ipwireless_debug; | 50 | int ipwireless_debug; |
51 | int ipwireless_loopback; | 51 | int ipwireless_loopback; |
52 | int ipwireless_out_queue = 1; | 52 | int ipwireless_out_queue = 10; |
53 | 53 | ||
54 | module_param_named(debug, ipwireless_debug, int, 0); | 54 | module_param_named(debug, ipwireless_debug, int, 0); |
55 | module_param_named(loopback, ipwireless_loopback, int, 0); | 55 | module_param_named(loopback, ipwireless_loopback, int, 0); |
@@ -57,7 +57,7 @@ module_param_named(out_queue, ipwireless_out_queue, int, 0); | |||
57 | MODULE_PARM_DESC(debug, "switch on debug messages [0]"); | 57 | MODULE_PARM_DESC(debug, "switch on debug messages [0]"); |
58 | MODULE_PARM_DESC(loopback, | 58 | MODULE_PARM_DESC(loopback, |
59 | "debug: enable ras_raw channel [0]"); | 59 | "debug: enable ras_raw channel [0]"); |
60 | MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]"); | 60 | MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); |
61 | 61 | ||
62 | /* Executes in process context. */ | 62 | /* Executes in process context. */ |
63 | static void signalled_reboot_work(struct work_struct *work_reboot) | 63 | static void signalled_reboot_work(struct work_struct *work_reboot) |
@@ -88,8 +88,6 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
88 | unsigned short buf[64]; | 88 | unsigned short buf[64]; |
89 | cisparse_t parse; | 89 | cisparse_t parse; |
90 | unsigned short cor_value; | 90 | unsigned short cor_value; |
91 | win_req_t request_attr_memory; | ||
92 | win_req_t request_common_memory; | ||
93 | memreq_t memreq_attr_memory; | 91 | memreq_t memreq_attr_memory; |
94 | memreq_t memreq_common_memory; | 92 | memreq_t memreq_common_memory; |
95 | 93 | ||
@@ -188,6 +186,9 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
188 | goto exit0; | 186 | goto exit0; |
189 | } | 187 | } |
190 | 188 | ||
189 | request_region(link->io.BasePort1, link->io.NumPorts1, | ||
190 | IPWIRELESS_PCCARD_NAME); | ||
191 | |||
191 | /* memory settings */ | 192 | /* memory settings */ |
192 | 193 | ||
193 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 194 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
@@ -214,16 +215,16 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
214 | } | 215 | } |
215 | 216 | ||
216 | if (parse.cftable_entry.mem.nwin > 0) { | 217 | if (parse.cftable_entry.mem.nwin > 0) { |
217 | request_common_memory.Attributes = | 218 | ipw->request_common_memory.Attributes = |
218 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | 219 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
219 | request_common_memory.Base = | 220 | ipw->request_common_memory.Base = |
220 | parse.cftable_entry.mem.win[0].host_addr; | 221 | parse.cftable_entry.mem.win[0].host_addr; |
221 | request_common_memory.Size = parse.cftable_entry.mem.win[0].len; | 222 | ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; |
222 | if (request_common_memory.Size < 0x1000) | 223 | if (ipw->request_common_memory.Size < 0x1000) |
223 | request_common_memory.Size = 0x1000; | 224 | ipw->request_common_memory.Size = 0x1000; |
224 | request_common_memory.AccessSpeed = 0; | 225 | ipw->request_common_memory.AccessSpeed = 0; |
225 | 226 | ||
226 | ret = pcmcia_request_window(&link, &request_common_memory, | 227 | ret = pcmcia_request_window(&link, &ipw->request_common_memory, |
227 | &ipw->handle_common_memory); | 228 | &ipw->handle_common_memory); |
228 | 229 | ||
229 | if (ret != CS_SUCCESS) { | 230 | if (ret != CS_SUCCESS) { |
@@ -246,16 +247,18 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
246 | ipw->is_v2_card = | 247 | ipw->is_v2_card = |
247 | parse.cftable_entry.mem.win[0].len == 0x100; | 248 | parse.cftable_entry.mem.win[0].len == 0x100; |
248 | 249 | ||
249 | ipw->common_memory = ioremap(request_common_memory.Base, | 250 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, |
250 | request_common_memory.Size); | 251 | ipw->request_common_memory.Size); |
252 | request_mem_region(ipw->request_common_memory.Base, | ||
253 | ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); | ||
251 | 254 | ||
252 | request_attr_memory.Attributes = | 255 | ipw->request_attr_memory.Attributes = |
253 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 256 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; |
254 | request_attr_memory.Base = 0; | 257 | ipw->request_attr_memory.Base = 0; |
255 | request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 258 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ |
256 | request_attr_memory.AccessSpeed = 0; | 259 | ipw->request_attr_memory.AccessSpeed = 0; |
257 | 260 | ||
258 | ret = pcmcia_request_window(&link, &request_attr_memory, | 261 | ret = pcmcia_request_window(&link, &ipw->request_attr_memory, |
259 | &ipw->handle_attr_memory); | 262 | &ipw->handle_attr_memory); |
260 | 263 | ||
261 | if (ret != CS_SUCCESS) { | 264 | if (ret != CS_SUCCESS) { |
@@ -274,8 +277,10 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
274 | goto exit2; | 277 | goto exit2; |
275 | } | 278 | } |
276 | 279 | ||
277 | ipw->attr_memory = ioremap(request_attr_memory.Base, | 280 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, |
278 | request_attr_memory.Size); | 281 | ipw->request_attr_memory.Size); |
282 | request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, | ||
283 | IPWIRELESS_PCCARD_NAME); | ||
279 | } | 284 | } |
280 | 285 | ||
281 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 286 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
@@ -311,14 +316,13 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
311 | (unsigned int) link->irq.AssignedIRQ); | 316 | (unsigned int) link->irq.AssignedIRQ); |
312 | if (ipw->attr_memory && ipw->common_memory) | 317 | if (ipw->attr_memory && ipw->common_memory) |
313 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 318 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
314 | ": attr memory 0x%08lx-0x%08lx, " | 319 | ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", |
315 | "common memory 0x%08lx-0x%08lx\n", | 320 | ipw->request_attr_memory.Base, |
316 | request_attr_memory.Base, | 321 | ipw->request_attr_memory.Base |
317 | request_attr_memory.Base | 322 | + ipw->request_attr_memory.Size - 1, |
318 | + request_attr_memory.Size - 1, | 323 | ipw->request_common_memory.Base, |
319 | request_common_memory.Base, | 324 | ipw->request_common_memory.Base |
320 | request_common_memory.Base | 325 | + ipw->request_common_memory.Size - 1); |
321 | + request_common_memory.Size - 1); | ||
322 | 326 | ||
323 | ipw->network = ipwireless_network_create(ipw->hardware); | 327 | ipw->network = ipwireless_network_create(ipw->hardware); |
324 | if (!ipw->network) | 328 | if (!ipw->network) |
@@ -350,12 +354,16 @@ exit4: | |||
350 | pcmcia_disable_device(link); | 354 | pcmcia_disable_device(link); |
351 | exit3: | 355 | exit3: |
352 | if (ipw->attr_memory) { | 356 | if (ipw->attr_memory) { |
357 | release_mem_region(ipw->request_attr_memory.Base, | ||
358 | ipw->request_attr_memory.Size); | ||
353 | iounmap(ipw->attr_memory); | 359 | iounmap(ipw->attr_memory); |
354 | pcmcia_release_window(ipw->handle_attr_memory); | 360 | pcmcia_release_window(ipw->handle_attr_memory); |
355 | pcmcia_disable_device(link); | 361 | pcmcia_disable_device(link); |
356 | } | 362 | } |
357 | exit2: | 363 | exit2: |
358 | if (ipw->common_memory) { | 364 | if (ipw->common_memory) { |
365 | release_mem_region(ipw->request_common_memory.Base, | ||
366 | ipw->request_common_memory.Size); | ||
359 | iounmap(ipw->common_memory); | 367 | iounmap(ipw->common_memory); |
360 | pcmcia_release_window(ipw->handle_common_memory); | 368 | pcmcia_release_window(ipw->handle_common_memory); |
361 | } | 369 | } |
@@ -367,19 +375,25 @@ exit0: | |||
367 | 375 | ||
368 | static void release_ipwireless(struct ipw_dev *ipw) | 376 | static void release_ipwireless(struct ipw_dev *ipw) |
369 | { | 377 | { |
370 | struct pcmcia_device *link = ipw->link; | 378 | pcmcia_disable_device(ipw->link); |
371 | |||
372 | pcmcia_disable_device(link); | ||
373 | 379 | ||
374 | if (ipw->common_memory) | 380 | if (ipw->common_memory) { |
381 | release_mem_region(ipw->request_common_memory.Base, | ||
382 | ipw->request_common_memory.Size); | ||
375 | iounmap(ipw->common_memory); | 383 | iounmap(ipw->common_memory); |
376 | if (ipw->attr_memory) | 384 | } |
385 | if (ipw->attr_memory) { | ||
386 | release_mem_region(ipw->request_attr_memory.Base, | ||
387 | ipw->request_attr_memory.Size); | ||
377 | iounmap(ipw->attr_memory); | 388 | iounmap(ipw->attr_memory); |
389 | } | ||
378 | if (ipw->common_memory) | 390 | if (ipw->common_memory) |
379 | pcmcia_release_window(ipw->handle_common_memory); | 391 | pcmcia_release_window(ipw->handle_common_memory); |
380 | if (ipw->attr_memory) | 392 | if (ipw->attr_memory) |
381 | pcmcia_release_window(ipw->handle_attr_memory); | 393 | pcmcia_release_window(ipw->handle_attr_memory); |
382 | pcmcia_disable_device(link); | 394 | |
395 | /* Break the link with Card Services */ | ||
396 | pcmcia_disable_device(ipw->link); | ||
383 | } | 397 | } |
384 | 398 | ||
385 | /* | 399 | /* |
@@ -437,10 +451,6 @@ static void ipwireless_detach(struct pcmcia_device *link) | |||
437 | 451 | ||
438 | release_ipwireless(ipw); | 452 | release_ipwireless(ipw); |
439 | 453 | ||
440 | /* Break the link with Card Services */ | ||
441 | if (link) | ||
442 | pcmcia_disable_device(link); | ||
443 | |||
444 | if (ipw->tty != NULL) | 454 | if (ipw->tty != NULL) |
445 | ipwireless_tty_free(ipw->tty); | 455 | ipwireless_tty_free(ipw->tty); |
446 | if (ipw->network != NULL) | 456 | if (ipw->network != NULL) |
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 1bfdcc8d47d6..0e0363af9ab2 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h | |||
@@ -45,10 +45,15 @@ struct ipw_tty; | |||
45 | struct ipw_dev { | 45 | struct ipw_dev { |
46 | struct pcmcia_device *link; | 46 | struct pcmcia_device *link; |
47 | int is_v2_card; | 47 | int is_v2_card; |
48 | |||
48 | window_handle_t handle_attr_memory; | 49 | window_handle_t handle_attr_memory; |
49 | void __iomem *attr_memory; | 50 | void __iomem *attr_memory; |
51 | win_req_t request_attr_memory; | ||
52 | |||
50 | window_handle_t handle_common_memory; | 53 | window_handle_t handle_common_memory; |
51 | void __iomem *common_memory; | 54 | void __iomem *common_memory; |
55 | win_req_t request_common_memory; | ||
56 | |||
52 | dev_node_t nodes[2]; | 57 | dev_node_t nodes[2]; |
53 | /* Reference to attribute memory, containing CIS data */ | 58 | /* Reference to attribute memory, containing CIS data */ |
54 | void *attribute_memory; | 59 | void *attribute_memory; |
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index fe914d34f7f6..590762a7f217 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "main.h" | 29 | #include "main.h" |
30 | #include "tty.h" | 30 | #include "tty.h" |
31 | 31 | ||
32 | #define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue | ||
33 | #define MAX_ASSOCIATED_TTYS 2 | 32 | #define MAX_ASSOCIATED_TTYS 2 |
34 | 33 | ||
35 | #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) | 34 | #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 { | |||
46 | /* Number of packets queued up in hardware module. */ | 45 | /* Number of packets queued up in hardware module. */ |
47 | int outgoing_packets_queued; | 46 | int outgoing_packets_queued; |
48 | /* Spinlock to avoid interrupts during shutdown */ | 47 | /* Spinlock to avoid interrupts during shutdown */ |
49 | spinlock_t spinlock; | 48 | spinlock_t lock; |
50 | struct mutex close_lock; | 49 | struct mutex close_lock; |
51 | 50 | ||
52 | /* PPP ioctl data, not actually used anywere */ | 51 | /* PPP ioctl data, not actually used anywere */ |
@@ -68,20 +67,20 @@ static void notify_packet_sent(void *callback_data, unsigned int packet_length) | |||
68 | struct ipw_network *network = callback_data; | 67 | struct ipw_network *network = callback_data; |
69 | unsigned long flags; | 68 | unsigned long flags; |
70 | 69 | ||
71 | spin_lock_irqsave(&network->spinlock, flags); | 70 | spin_lock_irqsave(&network->lock, flags); |
72 | network->outgoing_packets_queued--; | 71 | network->outgoing_packets_queued--; |
73 | if (network->ppp_channel != NULL) { | 72 | if (network->ppp_channel != NULL) { |
74 | if (network->ppp_blocked) { | 73 | if (network->ppp_blocked) { |
75 | network->ppp_blocked = 0; | 74 | network->ppp_blocked = 0; |
76 | spin_unlock_irqrestore(&network->spinlock, flags); | 75 | spin_unlock_irqrestore(&network->lock, flags); |
77 | ppp_output_wakeup(network->ppp_channel); | 76 | ppp_output_wakeup(network->ppp_channel); |
78 | if (ipwireless_debug) | 77 | if (ipwireless_debug) |
79 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 78 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME |
80 | ": ppp unblocked\n"); | 79 | ": ppp unblocked\n"); |
81 | } else | 80 | } else |
82 | spin_unlock_irqrestore(&network->spinlock, flags); | 81 | spin_unlock_irqrestore(&network->lock, flags); |
83 | } else | 82 | } else |
84 | spin_unlock_irqrestore(&network->spinlock, flags); | 83 | spin_unlock_irqrestore(&network->lock, flags); |
85 | } | 84 | } |
86 | 85 | ||
87 | /* | 86 | /* |
@@ -93,8 +92,8 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, | |||
93 | struct ipw_network *network = ppp_channel->private; | 92 | struct ipw_network *network = ppp_channel->private; |
94 | unsigned long flags; | 93 | unsigned long flags; |
95 | 94 | ||
96 | spin_lock_irqsave(&network->spinlock, flags); | 95 | spin_lock_irqsave(&network->lock, flags); |
97 | if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) { | 96 | if (network->outgoing_packets_queued < ipwireless_out_queue) { |
98 | unsigned char *buf; | 97 | unsigned char *buf; |
99 | static unsigned char header[] = { | 98 | static unsigned char header[] = { |
100 | PPP_ALLSTATIONS, /* 0xff */ | 99 | PPP_ALLSTATIONS, /* 0xff */ |
@@ -103,7 +102,7 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, | |||
103 | int ret; | 102 | int ret; |
104 | 103 | ||
105 | network->outgoing_packets_queued++; | 104 | network->outgoing_packets_queued++; |
106 | spin_unlock_irqrestore(&network->spinlock, flags); | 105 | spin_unlock_irqrestore(&network->lock, flags); |
107 | 106 | ||
108 | /* | 107 | /* |
109 | * If we have the requested amount of headroom in the skb we | 108 | * 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, | |||
144 | * needs to be unblocked once we are ready to send. | 143 | * needs to be unblocked once we are ready to send. |
145 | */ | 144 | */ |
146 | network->ppp_blocked = 1; | 145 | network->ppp_blocked = 1; |
147 | spin_unlock_irqrestore(&network->spinlock, flags); | 146 | spin_unlock_irqrestore(&network->lock, flags); |
147 | if (ipwireless_debug) | ||
148 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); | ||
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | } | 151 | } |
@@ -249,11 +250,11 @@ static void do_go_online(struct work_struct *work_go_online) | |||
249 | work_go_online); | 250 | work_go_online); |
250 | unsigned long flags; | 251 | unsigned long flags; |
251 | 252 | ||
252 | spin_lock_irqsave(&network->spinlock, flags); | 253 | spin_lock_irqsave(&network->lock, flags); |
253 | if (!network->ppp_channel) { | 254 | if (!network->ppp_channel) { |
254 | struct ppp_channel *channel; | 255 | struct ppp_channel *channel; |
255 | 256 | ||
256 | spin_unlock_irqrestore(&network->spinlock, flags); | 257 | spin_unlock_irqrestore(&network->lock, flags); |
257 | channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); | 258 | channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); |
258 | if (!channel) { | 259 | if (!channel) { |
259 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME | 260 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME |
@@ -273,10 +274,10 @@ static void do_go_online(struct work_struct *work_go_online) | |||
273 | network->xaccm[3] = 0x60000000U; | 274 | network->xaccm[3] = 0x60000000U; |
274 | network->raccm = ~0U; | 275 | network->raccm = ~0U; |
275 | ppp_register_channel(channel); | 276 | ppp_register_channel(channel); |
276 | spin_lock_irqsave(&network->spinlock, flags); | 277 | spin_lock_irqsave(&network->lock, flags); |
277 | network->ppp_channel = channel; | 278 | network->ppp_channel = channel; |
278 | } | 279 | } |
279 | spin_unlock_irqrestore(&network->spinlock, flags); | 280 | spin_unlock_irqrestore(&network->lock, flags); |
280 | } | 281 | } |
281 | 282 | ||
282 | static void do_go_offline(struct work_struct *work_go_offline) | 283 | 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) | |||
287 | unsigned long flags; | 288 | unsigned long flags; |
288 | 289 | ||
289 | mutex_lock(&network->close_lock); | 290 | mutex_lock(&network->close_lock); |
290 | spin_lock_irqsave(&network->spinlock, flags); | 291 | spin_lock_irqsave(&network->lock, flags); |
291 | if (network->ppp_channel != NULL) { | 292 | if (network->ppp_channel != NULL) { |
292 | struct ppp_channel *channel = network->ppp_channel; | 293 | struct ppp_channel *channel = network->ppp_channel; |
293 | 294 | ||
294 | network->ppp_channel = NULL; | 295 | network->ppp_channel = NULL; |
295 | spin_unlock_irqrestore(&network->spinlock, flags); | 296 | spin_unlock_irqrestore(&network->lock, flags); |
296 | mutex_unlock(&network->close_lock); | 297 | mutex_unlock(&network->close_lock); |
297 | ppp_unregister_channel(channel); | 298 | ppp_unregister_channel(channel); |
298 | } else { | 299 | } else { |
299 | spin_unlock_irqrestore(&network->spinlock, flags); | 300 | spin_unlock_irqrestore(&network->lock, flags); |
300 | mutex_unlock(&network->close_lock); | 301 | mutex_unlock(&network->close_lock); |
301 | } | 302 | } |
302 | } | 303 | } |
@@ -381,18 +382,18 @@ void ipwireless_network_packet_received(struct ipw_network *network, | |||
381 | * the PPP layer. | 382 | * the PPP layer. |
382 | */ | 383 | */ |
383 | mutex_lock(&network->close_lock); | 384 | mutex_lock(&network->close_lock); |
384 | spin_lock_irqsave(&network->spinlock, flags); | 385 | spin_lock_irqsave(&network->lock, flags); |
385 | if (network->ppp_channel != NULL) { | 386 | if (network->ppp_channel != NULL) { |
386 | struct sk_buff *skb; | 387 | struct sk_buff *skb; |
387 | 388 | ||
388 | spin_unlock_irqrestore(&network->spinlock, | 389 | spin_unlock_irqrestore(&network->lock, |
389 | flags); | 390 | flags); |
390 | 391 | ||
391 | /* Send the data to the ppp_generic module. */ | 392 | /* Send the data to the ppp_generic module. */ |
392 | skb = ipw_packet_received_skb(data, length); | 393 | skb = ipw_packet_received_skb(data, length); |
393 | ppp_input(network->ppp_channel, skb); | 394 | ppp_input(network->ppp_channel, skb); |
394 | } else | 395 | } else |
395 | spin_unlock_irqrestore(&network->spinlock, | 396 | spin_unlock_irqrestore(&network->lock, |
396 | flags); | 397 | flags); |
397 | mutex_unlock(&network->close_lock); | 398 | mutex_unlock(&network->close_lock); |
398 | } | 399 | } |
@@ -410,7 +411,7 @@ struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) | |||
410 | if (!network) | 411 | if (!network) |
411 | return NULL; | 412 | return NULL; |
412 | 413 | ||
413 | spin_lock_init(&network->spinlock); | 414 | spin_lock_init(&network->lock); |
414 | mutex_init(&network->close_lock); | 415 | mutex_init(&network->close_lock); |
415 | 416 | ||
416 | network->hardware = hw; | 417 | network->hardware = hw; |
@@ -478,10 +479,10 @@ int ipwireless_ppp_channel_index(struct ipw_network *network) | |||
478 | int ret = -1; | 479 | int ret = -1; |
479 | unsigned long flags; | 480 | unsigned long flags; |
480 | 481 | ||
481 | spin_lock_irqsave(&network->spinlock, flags); | 482 | spin_lock_irqsave(&network->lock, flags); |
482 | if (network->ppp_channel != NULL) | 483 | if (network->ppp_channel != NULL) |
483 | ret = ppp_channel_index(network->ppp_channel); | 484 | ret = ppp_channel_index(network->ppp_channel); |
484 | spin_unlock_irqrestore(&network->spinlock, flags); | 485 | spin_unlock_irqrestore(&network->lock, flags); |
485 | 486 | ||
486 | return ret; | 487 | return ret; |
487 | } | 488 | } |
@@ -491,10 +492,15 @@ int ipwireless_ppp_unit_number(struct ipw_network *network) | |||
491 | int ret = -1; | 492 | int ret = -1; |
492 | unsigned long flags; | 493 | unsigned long flags; |
493 | 494 | ||
494 | spin_lock_irqsave(&network->spinlock, flags); | 495 | spin_lock_irqsave(&network->lock, flags); |
495 | if (network->ppp_channel != NULL) | 496 | if (network->ppp_channel != NULL) |
496 | ret = ppp_unit_number(network->ppp_channel); | 497 | ret = ppp_unit_number(network->ppp_channel); |
497 | spin_unlock_irqrestore(&network->spinlock, flags); | 498 | spin_unlock_irqrestore(&network->lock, flags); |
498 | 499 | ||
499 | return ret; | 500 | return ret; |
500 | } | 501 | } |
502 | |||
503 | int ipwireless_ppp_mru(const struct ipw_network *network) | ||
504 | { | ||
505 | return network->mru; | ||
506 | } | ||
diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h index ccacd26fc7ef..561f765b3334 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); | |||
48 | void ipwireless_ppp_close(struct ipw_network *net); | 48 | void ipwireless_ppp_close(struct ipw_network *net); |
49 | int ipwireless_ppp_channel_index(struct ipw_network *net); | 49 | int ipwireless_ppp_channel_index(struct ipw_network *net); |
50 | int ipwireless_ppp_unit_number(struct ipw_network *net); | 50 | int ipwireless_ppp_unit_number(struct ipw_network *net); |
51 | int ipwireless_ppp_mru(const struct ipw_network *net); | ||
51 | 52 | ||
52 | #endif | 53 | #endif |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 42f3815c5ce3..b1414507997c 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, | |||
259 | } | 259 | } |
260 | 260 | ||
261 | ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, | 261 | ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, |
262 | (unsigned char *) buf, count, | 262 | buf, count, |
263 | ipw_write_packet_sent_callback, tty); | 263 | ipw_write_packet_sent_callback, tty); |
264 | if (ret == -1) { | 264 | if (ret == -1) { |
265 | mutex_unlock(&tty->ipw_tty_mutex); | 265 | mutex_unlock(&tty->ipw_tty_mutex); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 36a0afa89aaf..c240562c218b 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -2227,7 +2227,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
2227 | * Arguments: tty pointer to tty instance data | 2227 | * Arguments: tty pointer to tty instance data |
2228 | * break_state -1=set break condition, 0=clear | 2228 | * break_state -1=set break condition, 0=clear |
2229 | */ | 2229 | */ |
2230 | static void mgslpc_break(struct tty_struct *tty, int break_state) | 2230 | static int mgslpc_break(struct tty_struct *tty, int break_state) |
2231 | { | 2231 | { |
2232 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2232 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2233 | unsigned long flags; | 2233 | unsigned long flags; |
@@ -2237,7 +2237,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) | |||
2237 | __FILE__,__LINE__, info->device_name, break_state); | 2237 | __FILE__,__LINE__, info->device_name, break_state); |
2238 | 2238 | ||
2239 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) | 2239 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) |
2240 | return; | 2240 | return -EINVAL; |
2241 | 2241 | ||
2242 | spin_lock_irqsave(&info->lock,flags); | 2242 | spin_lock_irqsave(&info->lock,flags); |
2243 | if (break_state == -1) | 2243 | if (break_state == -1) |
@@ -2245,6 +2245,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) | |||
2245 | else | 2245 | else |
2246 | clear_reg_bits(info, CHA+DAFO, BIT6); | 2246 | clear_reg_bits(info, CHA+DAFO, BIT6); |
2247 | spin_unlock_irqrestore(&info->lock,flags); | 2247 | spin_unlock_irqrestore(&info->lock,flags); |
2248 | return 0; | ||
2248 | } | 2249 | } |
2249 | 2250 | ||
2250 | /* Service an IOCTL request | 2251 | /* Service an IOCTL request |
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index f6e6acadd9a0..bee39fdfba73 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -67,7 +67,7 @@ | |||
67 | #include <linux/major.h> | 67 | #include <linux/major.h> |
68 | #include <linux/ppdev.h> | 68 | #include <linux/ppdev.h> |
69 | #include <linux/smp_lock.h> | 69 | #include <linux/smp_lock.h> |
70 | #include <asm/uaccess.h> | 70 | #include <linux/uaccess.h> |
71 | 71 | ||
72 | #define PP_VERSION "ppdev: user-space parallel port driver" | 72 | #define PP_VERSION "ppdev: user-space parallel port driver" |
73 | #define CHRDEV "ppdev" | 73 | #define CHRDEV "ppdev" |
@@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode) | |||
328 | return IEEE1284_PH_FWD_IDLE; | 328 | return IEEE1284_PH_FWD_IDLE; |
329 | } | 329 | } |
330 | 330 | ||
331 | static int pp_ioctl(struct inode *inode, struct file *file, | 331 | static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
332 | unsigned int cmd, unsigned long arg) | ||
333 | { | 332 | { |
334 | unsigned int minor = iminor(inode); | 333 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
335 | struct pp_struct *pp = file->private_data; | 334 | struct pp_struct *pp = file->private_data; |
336 | struct parport * port; | 335 | struct parport * port; |
337 | void __user *argp = (void __user *)arg; | 336 | void __user *argp = (void __user *)arg; |
@@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file, | |||
634 | return 0; | 633 | return 0; |
635 | } | 634 | } |
636 | 635 | ||
636 | static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
637 | { | ||
638 | long ret; | ||
639 | lock_kernel(); | ||
640 | ret = pp_do_ioctl(file, cmd, arg); | ||
641 | unlock_kernel(); | ||
642 | return ret; | ||
643 | } | ||
644 | |||
637 | static int pp_open (struct inode * inode, struct file * file) | 645 | static int pp_open (struct inode * inode, struct file * file) |
638 | { | 646 | { |
639 | unsigned int minor = iminor(inode); | 647 | unsigned int minor = iminor(inode); |
@@ -745,15 +753,16 @@ static const struct file_operations pp_fops = { | |||
745 | .read = pp_read, | 753 | .read = pp_read, |
746 | .write = pp_write, | 754 | .write = pp_write, |
747 | .poll = pp_poll, | 755 | .poll = pp_poll, |
748 | .ioctl = pp_ioctl, | 756 | .unlocked_ioctl = pp_ioctl, |
749 | .open = pp_open, | 757 | .open = pp_open, |
750 | .release = pp_release, | 758 | .release = pp_release, |
751 | }; | 759 | }; |
752 | 760 | ||
753 | static void pp_attach(struct parport *port) | 761 | static void pp_attach(struct parport *port) |
754 | { | 762 | { |
755 | device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), | 763 | device_create_drvdata(ppdev_class, port->dev, |
756 | "parport%d", port->number); | 764 | MKDEV(PP_MAJOR, port->number), |
765 | NULL, "parport%d", port->number); | ||
757 | } | 766 | } |
758 | 767 | ||
759 | static void pp_detach(struct parport *port) | 768 | static void pp_detach(struct parport *port) |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 0cf98bd4f2d2..e0d0e371909c 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -236,6 +236,7 @@ | |||
236 | #include <linux/fs.h> | 236 | #include <linux/fs.h> |
237 | #include <linux/genhd.h> | 237 | #include <linux/genhd.h> |
238 | #include <linux/interrupt.h> | 238 | #include <linux/interrupt.h> |
239 | #include <linux/mm.h> | ||
239 | #include <linux/spinlock.h> | 240 | #include <linux/spinlock.h> |
240 | #include <linux/percpu.h> | 241 | #include <linux/percpu.h> |
241 | #include <linux/cryptohash.h> | 242 | #include <linux/cryptohash.h> |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 505fcbe884a4..47b8cf281d4a 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp, | |||
131 | static void bind_device(struct raw_config_request *rq) | 131 | static void bind_device(struct raw_config_request *rq) |
132 | { | 132 | { |
133 | device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); | 133 | device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); |
134 | device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), | 134 | device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), |
135 | "raw%d", rq->raw_minor); | 135 | NULL, "raw%d", rq->raw_minor); |
136 | } | 136 | } |
137 | 137 | ||
138 | /* | 138 | /* |
@@ -283,7 +283,8 @@ static int __init raw_init(void) | |||
283 | ret = PTR_ERR(raw_class); | 283 | ret = PTR_ERR(raw_class); |
284 | goto error_region; | 284 | goto error_region; |
285 | } | 285 | } |
286 | device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl"); | 286 | device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, |
287 | "rawctl"); | ||
287 | 288 | ||
288 | return 0; | 289 | return 0; |
289 | 290 | ||
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 0cdfee152916..a8f68a3f14dd 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); | |||
179 | static void rio_hungup(void *ptr); | 179 | static void rio_hungup(void *ptr); |
180 | static void rio_close(void *ptr); | 180 | static void rio_close(void *ptr); |
181 | static int rio_chars_in_buffer(void *ptr); | 181 | static int rio_chars_in_buffer(void *ptr); |
182 | static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); | 182 | static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); |
183 | static int rio_init_drivers(void); | 183 | static int rio_init_drivers(void); |
184 | 184 | ||
185 | static void my_hd(void *addr, int len); | 185 | static void my_hd(void *addr, int len); |
@@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = { | |||
240 | 240 | ||
241 | static const struct file_operations rio_fw_fops = { | 241 | static const struct file_operations rio_fw_fops = { |
242 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
243 | .ioctl = rio_fw_ioctl, | 243 | .unlocked_ioctl = rio_fw_ioctl, |
244 | }; | 244 | }; |
245 | 245 | ||
246 | static struct miscdevice rio_fw_device = { | 246 | static struct miscdevice rio_fw_device = { |
@@ -560,13 +560,15 @@ static void rio_close(void *ptr) | |||
560 | 560 | ||
561 | 561 | ||
562 | 562 | ||
563 | static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) | 563 | static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
564 | { | 564 | { |
565 | int rc = 0; | 565 | int rc = 0; |
566 | func_enter(); | 566 | func_enter(); |
567 | 567 | ||
568 | /* The "dev" argument isn't used. */ | 568 | /* The "dev" argument isn't used. */ |
569 | lock_kernel(); | ||
569 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); | 570 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); |
571 | unlock_kernel(); | ||
570 | 572 | ||
571 | func_exit(); | 573 | func_exit(); |
572 | return rc; | 574 | return rc; |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 724b2b20f4b2..2c6c8f33d6b4 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -1250,11 +1250,15 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1250 | return 0; | 1250 | return 0; |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | static void rc_send_break(struct riscom_port *port, unsigned long length) | 1253 | static int rc_send_break(struct tty_struct *tty, int length) |
1254 | { | 1254 | { |
1255 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | ||
1255 | struct riscom_board *bp = port_Board(port); | 1256 | struct riscom_board *bp = port_Board(port); |
1256 | unsigned long flags; | 1257 | unsigned long flags; |
1257 | 1258 | ||
1259 | if (length == 0 || length == -1) | ||
1260 | return -EOPNOTSUPP; | ||
1261 | |||
1258 | spin_lock_irqsave(&riscom_lock, flags); | 1262 | spin_lock_irqsave(&riscom_lock, flags); |
1259 | 1263 | ||
1260 | port->break_length = RISCOM_TPS / HZ * length; | 1264 | port->break_length = RISCOM_TPS / HZ * length; |
@@ -1268,6 +1272,7 @@ static void rc_send_break(struct riscom_port *port, unsigned long length) | |||
1268 | rc_wait_CCR(bp); | 1272 | rc_wait_CCR(bp); |
1269 | 1273 | ||
1270 | spin_unlock_irqrestore(&riscom_lock, flags); | 1274 | spin_unlock_irqrestore(&riscom_lock, flags); |
1275 | return 0; | ||
1271 | } | 1276 | } |
1272 | 1277 | ||
1273 | static int rc_set_serial_info(struct riscom_port *port, | 1278 | static int rc_set_serial_info(struct riscom_port *port, |
@@ -1342,27 +1347,12 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, | |||
1342 | { | 1347 | { |
1343 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1348 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; |
1344 | void __user *argp = (void __user *)arg; | 1349 | void __user *argp = (void __user *)arg; |
1345 | int retval = 0; | 1350 | int retval; |
1346 | 1351 | ||
1347 | if (rc_paranoia_check(port, tty->name, "rc_ioctl")) | 1352 | if (rc_paranoia_check(port, tty->name, "rc_ioctl")) |
1348 | return -ENODEV; | 1353 | return -ENODEV; |
1349 | 1354 | ||
1350 | switch (cmd) { | 1355 | switch (cmd) { |
1351 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
1352 | retval = tty_check_change(tty); | ||
1353 | if (retval) | ||
1354 | return retval; | ||
1355 | tty_wait_until_sent(tty, 0); | ||
1356 | if (!arg) | ||
1357 | rc_send_break(port, HZ/4); /* 1/4 second */ | ||
1358 | break; | ||
1359 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
1360 | retval = tty_check_change(tty); | ||
1361 | if (retval) | ||
1362 | return retval; | ||
1363 | tty_wait_until_sent(tty, 0); | ||
1364 | rc_send_break(port, arg ? arg*(HZ/10) : HZ/4); | ||
1365 | break; | ||
1366 | case TIOCGSERIAL: | 1356 | case TIOCGSERIAL: |
1367 | lock_kernel(); | 1357 | lock_kernel(); |
1368 | retval = rc_get_serial_info(port, argp); | 1358 | retval = rc_get_serial_info(port, argp); |
@@ -1517,6 +1507,7 @@ static const struct tty_operations riscom_ops = { | |||
1517 | .hangup = rc_hangup, | 1507 | .hangup = rc_hangup, |
1518 | .tiocmget = rc_tiocmget, | 1508 | .tiocmget = rc_tiocmget, |
1519 | .tiocmset = rc_tiocmset, | 1509 | .tiocmset = rc_tiocmset, |
1510 | .break_ctl = rc_send_break, | ||
1520 | }; | 1511 | }; |
1521 | 1512 | ||
1522 | static int __init rc_init_drivers(void) | 1513 | static int __init rc_init_drivers(void) |
@@ -1538,7 +1529,7 @@ static int __init rc_init_drivers(void) | |||
1538 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 1529 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
1539 | riscom_driver->init_termios.c_ispeed = 9600; | 1530 | riscom_driver->init_termios.c_ispeed = 9600; |
1540 | riscom_driver->init_termios.c_ospeed = 9600; | 1531 | riscom_driver->init_termios.c_ospeed = 9600; |
1541 | riscom_driver->flags = TTY_DRIVER_REAL_RAW; | 1532 | riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; |
1542 | tty_set_operations(riscom_driver, &riscom_ops); | 1533 | tty_set_operations(riscom_driver, &riscom_ops); |
1543 | error = tty_register_driver(riscom_driver); | 1534 | error = tty_register_driver(riscom_driver); |
1544 | if (error != 0) { | 1535 | if (error != 0) { |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index e670eae2f510..584d791e84a6 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty, | |||
1236 | } | 1236 | } |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | static void rp_break(struct tty_struct *tty, int break_state) | 1239 | static int rp_break(struct tty_struct *tty, int break_state) |
1240 | { | 1240 | { |
1241 | struct r_port *info = (struct r_port *) tty->driver_data; | 1241 | struct r_port *info = (struct r_port *) tty->driver_data; |
1242 | unsigned long flags; | 1242 | unsigned long flags; |
1243 | 1243 | ||
1244 | if (rocket_paranoia_check(info, "rp_break")) | 1244 | if (rocket_paranoia_check(info, "rp_break")) |
1245 | return; | 1245 | return -EINVAL; |
1246 | 1246 | ||
1247 | spin_lock_irqsave(&info->slock, flags); | 1247 | spin_lock_irqsave(&info->slock, flags); |
1248 | if (break_state == -1) | 1248 | if (break_state == -1) |
@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state) | |||
1250 | else | 1250 | else |
1251 | sClrBreak(&info->channel); | 1251 | sClrBreak(&info->channel); |
1252 | spin_unlock_irqrestore(&info->slock, flags); | 1252 | spin_unlock_irqrestore(&info->slock, flags); |
1253 | return 0; | ||
1253 | } | 1254 | } |
1254 | 1255 | ||
1255 | /* | 1256 | /* |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index fa92a8af5a5a..d9799e2bcfbf 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -78,9 +78,10 @@ | |||
78 | #include <linux/wait.h> | 78 | #include <linux/wait.h> |
79 | #include <linux/bcd.h> | 79 | #include <linux/bcd.h> |
80 | #include <linux/delay.h> | 80 | #include <linux/delay.h> |
81 | #include <linux/smp_lock.h> | ||
82 | #include <linux/uaccess.h> | ||
81 | 83 | ||
82 | #include <asm/current.h> | 84 | #include <asm/current.h> |
83 | #include <asm/uaccess.h> | ||
84 | #include <asm/system.h> | 85 | #include <asm/system.h> |
85 | 86 | ||
86 | #ifdef CONFIG_X86 | 87 | #ifdef CONFIG_X86 |
@@ -120,8 +121,6 @@ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | |||
120 | return 0; | 121 | return 0; |
121 | } | 122 | } |
122 | #endif | 123 | #endif |
123 | #else | ||
124 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
125 | #endif | 124 | #endif |
126 | 125 | ||
127 | /* | 126 | /* |
@@ -144,8 +143,8 @@ static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0); | |||
144 | static ssize_t rtc_read(struct file *file, char __user *buf, | 143 | static ssize_t rtc_read(struct file *file, char __user *buf, |
145 | size_t count, loff_t *ppos); | 144 | size_t count, loff_t *ppos); |
146 | 145 | ||
147 | static int rtc_ioctl(struct inode *inode, struct file *file, | 146 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
148 | unsigned int cmd, unsigned long arg); | 147 | static void rtc_get_rtc_time(struct rtc_time *rtc_tm); |
149 | 148 | ||
150 | #ifdef RTC_IRQ | 149 | #ifdef RTC_IRQ |
151 | static unsigned int rtc_poll(struct file *file, poll_table *wait); | 150 | static unsigned int rtc_poll(struct file *file, poll_table *wait); |
@@ -237,7 +236,7 @@ static inline unsigned char rtc_is_updating(void) | |||
237 | * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) | 236 | * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) |
238 | */ | 237 | */ |
239 | 238 | ||
240 | irqreturn_t rtc_interrupt(int irq, void *dev_id) | 239 | static irqreturn_t rtc_interrupt(int irq, void *dev_id) |
241 | { | 240 | { |
242 | /* | 241 | /* |
243 | * Can be an alarm interrupt, update complete interrupt, | 242 | * Can be an alarm interrupt, update complete interrupt, |
@@ -719,10 +718,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) | |||
719 | &wtime, sizeof wtime) ? -EFAULT : 0; | 718 | &wtime, sizeof wtime) ? -EFAULT : 0; |
720 | } | 719 | } |
721 | 720 | ||
722 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 721 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
723 | unsigned long arg) | ||
724 | { | 722 | { |
725 | return rtc_do_ioctl(cmd, arg, 0); | 723 | long ret; |
724 | lock_kernel(); | ||
725 | ret = rtc_do_ioctl(cmd, arg, 0); | ||
726 | unlock_kernel(); | ||
727 | return ret; | ||
726 | } | 728 | } |
727 | 729 | ||
728 | /* | 730 | /* |
@@ -915,7 +917,7 @@ static const struct file_operations rtc_fops = { | |||
915 | #ifdef RTC_IRQ | 917 | #ifdef RTC_IRQ |
916 | .poll = rtc_poll, | 918 | .poll = rtc_poll, |
917 | #endif | 919 | #endif |
918 | .ioctl = rtc_ioctl, | 920 | .unlocked_ioctl = rtc_ioctl, |
919 | .open = rtc_open, | 921 | .open = rtc_open, |
920 | .release = rtc_release, | 922 | .release = rtc_release, |
921 | .fasync = rtc_fasync, | 923 | .fasync = rtc_fasync, |
@@ -1302,7 +1304,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) | |||
1302 | } | 1304 | } |
1303 | #endif | 1305 | #endif |
1304 | 1306 | ||
1305 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) | 1307 | static void rtc_get_rtc_time(struct rtc_time *rtc_tm) |
1306 | { | 1308 | { |
1307 | unsigned long uip_watchdog = jiffies, flags; | 1309 | unsigned long uip_watchdog = jiffies, flags; |
1308 | unsigned char ctrl; | 1310 | unsigned char ctrl; |
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 4ba3aec9e1cd..7b0c35207d9b 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) | |||
192 | Maybe one could implement a more efficient version by not only | 192 | Maybe one could implement a more efficient version by not only |
193 | transferring one character at a time. | 193 | transferring one character at a time. |
194 | */ | 194 | */ |
195 | struct tty_struct *tty = port->gs.tty; | 195 | struct tty_struct *tty = port->gs.port.tty; |
196 | 196 | ||
197 | #if 0 | 197 | #if 0 |
198 | switch(err) { | 198 | switch(err) { |
@@ -226,7 +226,7 @@ static void a2232_disable_tx_interrupts(void *ptr) | |||
226 | 226 | ||
227 | /* Does this here really have to be? */ | 227 | /* Does this here really have to be? */ |
228 | local_irq_save(flags); | 228 | local_irq_save(flags); |
229 | port->gs.flags &= ~GS_TX_INTEN; | 229 | port->gs.port.flags &= ~GS_TX_INTEN; |
230 | local_irq_restore(flags); | 230 | local_irq_restore(flags); |
231 | } | 231 | } |
232 | 232 | ||
@@ -242,7 +242,7 @@ static void a2232_enable_tx_interrupts(void *ptr) | |||
242 | 242 | ||
243 | /* Does this here really have to be? */ | 243 | /* Does this here really have to be? */ |
244 | local_irq_save(flags); | 244 | local_irq_save(flags); |
245 | port->gs.flags |= GS_TX_INTEN; | 245 | port->gs.port.flags |= GS_TX_INTEN; |
246 | local_irq_restore(flags); | 246 | local_irq_restore(flags); |
247 | } | 247 | } |
248 | 248 | ||
@@ -276,9 +276,9 @@ static void a2232_shutdown_port(void *ptr) | |||
276 | 276 | ||
277 | local_irq_save(flags); | 277 | local_irq_save(flags); |
278 | 278 | ||
279 | port->gs.flags &= ~GS_ACTIVE; | 279 | port->gs.port.flags &= ~GS_ACTIVE; |
280 | 280 | ||
281 | if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { | 281 | if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { |
282 | /* Set DTR and RTS to Low, flush output. | 282 | /* Set DTR and RTS to Low, flush output. |
283 | The NetBSD driver "msc.c" does it this way. */ | 283 | The NetBSD driver "msc.c" does it this way. */ |
284 | stat->Command = ( (stat->Command & ~A2232CMD_CMask) | | 284 | stat->Command = ( (stat->Command & ~A2232CMD_CMask) | |
@@ -309,7 +309,7 @@ static int a2232_set_real_termios(void *ptr) | |||
309 | volatile struct a2232status *status; | 309 | volatile struct a2232status *status; |
310 | volatile struct a2232memory *mem; | 310 | volatile struct a2232memory *mem; |
311 | 311 | ||
312 | if (!port->gs.tty || !port->gs.tty->termios) return 0; | 312 | if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; |
313 | 313 | ||
314 | status = a2232stat(port->which_a2232, port->which_port_on_a2232); | 314 | status = a2232stat(port->which_a2232, port->which_port_on_a2232); |
315 | mem = a2232mem(port->which_a2232); | 315 | mem = a2232mem(port->which_a2232); |
@@ -345,7 +345,7 @@ static int a2232_set_real_termios(void *ptr) | |||
345 | } | 345 | } |
346 | a2232_param |= rate; | 346 | a2232_param |= rate; |
347 | 347 | ||
348 | cflag = port->gs.tty->termios->c_cflag; | 348 | cflag = port->gs.port.tty->termios->c_cflag; |
349 | 349 | ||
350 | // get character size | 350 | // get character size |
351 | chsize = cflag & CSIZE; | 351 | chsize = cflag & CSIZE; |
@@ -382,7 +382,7 @@ static int a2232_set_real_termios(void *ptr) | |||
382 | the conventional way of inserting START/STOP characters | 382 | the conventional way of inserting START/STOP characters |
383 | by hand in throttle()/unthrottle(). | 383 | by hand in throttle()/unthrottle(). |
384 | */ | 384 | */ |
385 | softflow = !!( port->gs.tty->termios->c_iflag & IXOFF ); | 385 | softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF ); |
386 | 386 | ||
387 | // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) | 387 | // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) |
388 | parity = cflag & (PARENB | PARODD); | 388 | parity = cflag & (PARENB | PARODD); |
@@ -400,9 +400,9 @@ static int a2232_set_real_termios(void *ptr) | |||
400 | /* Hmm. Maybe an own a2232_port structure | 400 | /* Hmm. Maybe an own a2232_port structure |
401 | member would be cleaner? */ | 401 | member would be cleaner? */ |
402 | if (cflag & CLOCAL) | 402 | if (cflag & CLOCAL) |
403 | port->gs.flags &= ~ASYNC_CHECK_CD; | 403 | port->gs.port.flags &= ~ASYNC_CHECK_CD; |
404 | else | 404 | else |
405 | port->gs.flags |= ASYNC_CHECK_CD; | 405 | port->gs.port.flags |= ASYNC_CHECK_CD; |
406 | 406 | ||
407 | 407 | ||
408 | /* Now we have all parameters and can go to set them: */ | 408 | /* 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) | |||
482 | port = &a2232_ports[line]; | 482 | port = &a2232_ports[line]; |
483 | 483 | ||
484 | tty->driver_data = port; | 484 | tty->driver_data = port; |
485 | port->gs.tty = tty; | 485 | port->gs.port.tty = tty; |
486 | port->gs.count++; | 486 | port->gs.port.count++; |
487 | retval = gs_init_port(&port->gs); | 487 | retval = gs_init_port(&port->gs); |
488 | if (retval) { | 488 | if (retval) { |
489 | port->gs.count--; | 489 | port->gs.port.count--; |
490 | return retval; | 490 | return retval; |
491 | } | 491 | } |
492 | port->gs.flags |= GS_ACTIVE; | 492 | port->gs.port.flags |= GS_ACTIVE; |
493 | retval = gs_block_til_ready(port, filp); | 493 | retval = gs_block_til_ready(port, filp); |
494 | 494 | ||
495 | if (retval) { | 495 | if (retval) { |
496 | port->gs.count--; | 496 | port->gs.port.count--; |
497 | return retval; | 497 | return retval; |
498 | } | 498 | } |
499 | 499 | ||
@@ -522,7 +522,7 @@ int ch, err, n, p; | |||
522 | for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ | 522 | for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ |
523 | err = 0; | 523 | err = 0; |
524 | port = &a2232_ports[n*NUMLINES+p]; | 524 | port = &a2232_ports[n*NUMLINES+p]; |
525 | if ( port->gs.flags & GS_ACTIVE ){ /* if the port is used */ | 525 | if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */ |
526 | 526 | ||
527 | status = a2232stat(n,p); | 527 | status = a2232stat(n,p); |
528 | 528 | ||
@@ -577,8 +577,8 @@ int ch, err, n, p; | |||
577 | obuf = mem->OutBuf[p]; | 577 | obuf = mem->OutBuf[p]; |
578 | bufpos = status->OutHead; | 578 | bufpos = status->OutHead; |
579 | while ( (port->gs.xmit_cnt > 0) && | 579 | while ( (port->gs.xmit_cnt > 0) && |
580 | (!port->gs.tty->stopped) && | 580 | (!port->gs.port.tty->stopped) && |
581 | (!port->gs.tty->hw_stopped) ){ /* While there are chars to transmit */ | 581 | (!port->gs.port.tty->hw_stopped) ){ /* While there are chars to transmit */ |
582 | if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ | 582 | if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ |
583 | ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ | 583 | ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ |
584 | port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */ | 584 | 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; | |||
592 | status->OutHead = bufpos; | 592 | status->OutHead = bufpos; |
593 | 593 | ||
594 | /* WakeUp if output buffer runs low */ | 594 | /* WakeUp if output buffer runs low */ |
595 | if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { | 595 | if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { |
596 | tty_wakeup(port->gs.tty); | 596 | tty_wakeup(port->gs.port.tty); |
597 | } | 597 | } |
598 | } // if the port is used | 598 | } // if the port is used |
599 | } // for every port on the board | 599 | } // for every port on the board |
@@ -613,16 +613,16 @@ int ch, err, n, p; | |||
613 | struct a2232_port *port = &a2232_ports[n*7+p]; | 613 | struct a2232_port *port = &a2232_ports[n*7+p]; |
614 | port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ | 614 | port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ |
615 | 615 | ||
616 | if (!(port->gs.flags & ASYNC_CHECK_CD)) | 616 | if (!(port->gs.port.flags & ASYNC_CHECK_CD)) |
617 | ; /* Don't report DCD changes */ | 617 | ; /* Don't report DCD changes */ |
618 | else if (port->cd_status) { // if DCD on: DCD went UP! | 618 | else if (port->cd_status) { // if DCD on: DCD went UP! |
619 | 619 | ||
620 | /* Are we blocking in open?*/ | 620 | /* Are we blocking in open?*/ |
621 | wake_up_interruptible(&port->gs.open_wait); | 621 | wake_up_interruptible(&port->gs.port.open_wait); |
622 | } | 622 | } |
623 | else { // if DCD off: DCD went DOWN! | 623 | else { // if DCD off: DCD went DOWN! |
624 | if (port->gs.tty) | 624 | if (port->gs.port.tty) |
625 | tty_hangup (port->gs.tty); | 625 | tty_hangup (port->gs.port.tty); |
626 | } | 626 | } |
627 | 627 | ||
628 | } // if CD changed for this port | 628 | } // if CD changed for this port |
@@ -655,8 +655,8 @@ static void a2232_init_portstructs(void) | |||
655 | #ifdef NEW_WRITE_LOCKING | 655 | #ifdef NEW_WRITE_LOCKING |
656 | mutex_init(&(port->gs.port_write_mutex)); | 656 | mutex_init(&(port->gs.port_write_mutex)); |
657 | #endif | 657 | #endif |
658 | init_waitqueue_head(&port->gs.open_wait); | 658 | init_waitqueue_head(&port->gs.port.open_wait); |
659 | init_waitqueue_head(&port->gs.close_wait); | 659 | init_waitqueue_head(&port->gs.port.close_wait); |
660 | } | 660 | } |
661 | } | 661 | } |
662 | 662 | ||
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 0b799ac1b049..3ce60df14c0a 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
@@ -444,7 +444,8 @@ scdrv_init(void) | |||
444 | continue; | 444 | continue; |
445 | } | 445 | } |
446 | 446 | ||
447 | device_create(snsc_class, NULL, dev, "%s", devname); | 447 | device_create_drvdata(snsc_class, NULL, dev, NULL, |
448 | "%s", devname); | ||
448 | 449 | ||
449 | ia64_sn_irtr_intr_enable(scd->scd_nasid, | 450 | ia64_sn_irtr_intr_enable(scd->scd_nasid, |
450 | 0 /*ignored */ , | 451 | 0 /*ignored */ , |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 037dc47e4cb1..242fd46fda22 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -77,7 +77,7 @@ | |||
77 | 77 | ||
78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
79 | 79 | ||
80 | #include <asm/io.h> | 80 | #include <linux/io.h> |
81 | #include <linux/kernel.h> | 81 | #include <linux/kernel.h> |
82 | #include <linux/sched.h> | 82 | #include <linux/sched.h> |
83 | #include <linux/ioport.h> | 83 | #include <linux/ioport.h> |
@@ -92,7 +92,7 @@ | |||
92 | #include <linux/delay.h> | 92 | #include <linux/delay.h> |
93 | #include <linux/pci.h> | 93 | #include <linux/pci.h> |
94 | #include <linux/init.h> | 94 | #include <linux/init.h> |
95 | #include <asm/uaccess.h> | 95 | #include <linux/uaccess.h> |
96 | 96 | ||
97 | #include "specialix_io8.h" | 97 | #include "specialix_io8.h" |
98 | #include "cd1865.h" | 98 | #include "cd1865.h" |
@@ -110,9 +110,10 @@ | |||
110 | 110 | ||
111 | static int sx_debug; | 111 | static int sx_debug; |
112 | static int sx_rxfifo = SPECIALIX_RXFIFO; | 112 | static int sx_rxfifo = SPECIALIX_RXFIFO; |
113 | static int sx_rtscts; | ||
113 | 114 | ||
114 | #ifdef DEBUG | 115 | #ifdef DEBUG |
115 | #define dprintk(f, str...) if (sx_debug & f) printk (str) | 116 | #define dprintk(f, str...) if (sx_debug & f) printk(str) |
116 | #else | 117 | #else |
117 | #define dprintk(f, str...) /* nothing */ | 118 | #define dprintk(f, str...) /* nothing */ |
118 | #endif | 119 | #endif |
@@ -131,10 +132,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; | |||
131 | #define SX_DEBUG_FIFO 0x0800 | 132 | #define SX_DEBUG_FIFO 0x0800 |
132 | 133 | ||
133 | 134 | ||
134 | #define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__) | 135 | #define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) |
135 | #define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__) | 136 | #define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) |
136 | |||
137 | #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) | ||
138 | 137 | ||
139 | 138 | ||
140 | /* Configurable options: */ | 139 | /* Configurable options: */ |
@@ -142,17 +141,6 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; | |||
142 | /* Am I paranoid or not ? ;-) */ | 141 | /* Am I paranoid or not ? ;-) */ |
143 | #define SPECIALIX_PARANOIA_CHECK | 142 | #define SPECIALIX_PARANOIA_CHECK |
144 | 143 | ||
145 | /* Do I trust the IRQ from the card? (enabeling it doesn't seem to help) | ||
146 | When the IRQ routine leaves the chip in a state that is keeps on | ||
147 | requiring attention, the timer doesn't help either. */ | ||
148 | #undef SPECIALIX_TIMER | ||
149 | |||
150 | #ifdef SPECIALIX_TIMER | ||
151 | static int sx_poll = HZ; | ||
152 | #endif | ||
153 | |||
154 | |||
155 | |||
156 | /* | 144 | /* |
157 | * The following defines are mostly for testing purposes. But if you need | 145 | * The following defines are mostly for testing purposes. But if you need |
158 | * some nice reporting in your syslog, you can define them also. | 146 | * some nice reporting in your syslog, you can define them also. |
@@ -162,16 +150,6 @@ static int sx_poll = HZ; | |||
162 | 150 | ||
163 | 151 | ||
164 | 152 | ||
165 | #ifdef CONFIG_SPECIALIX_RTSCTS | ||
166 | #define SX_CRTSCTS(bla) 1 | ||
167 | #else | ||
168 | #define SX_CRTSCTS(tty) C_CRTSCTS(tty) | ||
169 | #endif | ||
170 | |||
171 | |||
172 | /* Used to be outb (0xff, 0x80); */ | ||
173 | #define short_pause() udelay (1) | ||
174 | |||
175 | 153 | ||
176 | #define SPECIALIX_LEGAL_FLAGS \ | 154 | #define SPECIALIX_LEGAL_FLAGS \ |
177 | (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ | 155 | (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ |
@@ -190,21 +168,14 @@ static struct specialix_board sx_board[SX_NBOARD] = { | |||
190 | static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; | 168 | static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; |
191 | 169 | ||
192 | 170 | ||
193 | #ifdef SPECIALIX_TIMER | 171 | static int sx_paranoia_check(struct specialix_port const *port, |
194 | static struct timer_list missed_irq_timer; | ||
195 | static irqreturn_t sx_interrupt(int irq, void * dev_id); | ||
196 | #endif | ||
197 | |||
198 | |||
199 | |||
200 | static inline int sx_paranoia_check(struct specialix_port const * port, | ||
201 | char *name, const char *routine) | 172 | char *name, const char *routine) |
202 | { | 173 | { |
203 | #ifdef SPECIALIX_PARANOIA_CHECK | 174 | #ifdef SPECIALIX_PARANOIA_CHECK |
204 | static const char *badmagic = | 175 | static const char *badmagic = KERN_ERR |
205 | KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; | 176 | "sx: Warning: bad specialix port magic number for device %s in %s\n"; |
206 | static const char *badinfo = | 177 | static const char *badinfo = KERN_ERR |
207 | KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; | 178 | "sx: Warning: null specialix port for device %s in %s\n"; |
208 | 179 | ||
209 | if (!port) { | 180 | if (!port) { |
210 | printk(badinfo, name, routine); | 181 | printk(badinfo, name, routine); |
@@ -226,66 +197,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port, | |||
226 | */ | 197 | */ |
227 | 198 | ||
228 | /* Get board number from pointer */ | 199 | /* Get board number from pointer */ |
229 | static inline int board_No (struct specialix_board * bp) | 200 | static inline int board_No(struct specialix_board *bp) |
230 | { | 201 | { |
231 | return bp - sx_board; | 202 | return bp - sx_board; |
232 | } | 203 | } |
233 | 204 | ||
234 | 205 | ||
235 | /* Get port number from pointer */ | 206 | /* Get port number from pointer */ |
236 | static inline int port_No (struct specialix_port const * port) | 207 | static inline int port_No(struct specialix_port const *port) |
237 | { | 208 | { |
238 | return SX_PORT(port - sx_port); | 209 | return SX_PORT(port - sx_port); |
239 | } | 210 | } |
240 | 211 | ||
241 | 212 | ||
242 | /* Get pointer to board from pointer to port */ | 213 | /* Get pointer to board from pointer to port */ |
243 | static inline struct specialix_board * port_Board(struct specialix_port const * port) | 214 | static inline struct specialix_board *port_Board( |
215 | struct specialix_port const *port) | ||
244 | { | 216 | { |
245 | return &sx_board[SX_BOARD(port - sx_port)]; | 217 | return &sx_board[SX_BOARD(port - sx_port)]; |
246 | } | 218 | } |
247 | 219 | ||
248 | 220 | ||
249 | /* Input Byte from CL CD186x register */ | 221 | /* Input Byte from CL CD186x register */ |
250 | static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg) | 222 | static inline unsigned char sx_in(struct specialix_board *bp, |
223 | unsigned short reg) | ||
251 | { | 224 | { |
252 | bp->reg = reg | 0x80; | 225 | bp->reg = reg | 0x80; |
253 | outb (reg | 0x80, bp->base + SX_ADDR_REG); | 226 | outb(reg | 0x80, bp->base + SX_ADDR_REG); |
254 | return inb (bp->base + SX_DATA_REG); | 227 | return inb(bp->base + SX_DATA_REG); |
255 | } | 228 | } |
256 | 229 | ||
257 | 230 | ||
258 | /* Output Byte to CL CD186x register */ | 231 | /* Output Byte to CL CD186x register */ |
259 | static inline void sx_out(struct specialix_board * bp, unsigned short reg, | 232 | static inline void sx_out(struct specialix_board *bp, unsigned short reg, |
260 | unsigned char val) | 233 | unsigned char val) |
261 | { | 234 | { |
262 | bp->reg = reg | 0x80; | 235 | bp->reg = reg | 0x80; |
263 | outb (reg | 0x80, bp->base + SX_ADDR_REG); | 236 | outb(reg | 0x80, bp->base + SX_ADDR_REG); |
264 | outb (val, bp->base + SX_DATA_REG); | 237 | outb(val, bp->base + SX_DATA_REG); |
265 | } | 238 | } |
266 | 239 | ||
267 | 240 | ||
268 | /* Input Byte from CL CD186x register */ | 241 | /* Input Byte from CL CD186x register */ |
269 | static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg) | 242 | static inline unsigned char sx_in_off(struct specialix_board *bp, |
243 | unsigned short reg) | ||
270 | { | 244 | { |
271 | bp->reg = reg; | 245 | bp->reg = reg; |
272 | outb (reg, bp->base + SX_ADDR_REG); | 246 | outb(reg, bp->base + SX_ADDR_REG); |
273 | return inb (bp->base + SX_DATA_REG); | 247 | return inb(bp->base + SX_DATA_REG); |
274 | } | 248 | } |
275 | 249 | ||
276 | 250 | ||
277 | /* Output Byte to CL CD186x register */ | 251 | /* Output Byte to CL CD186x register */ |
278 | static inline void sx_out_off(struct specialix_board * bp, unsigned short reg, | 252 | static inline void sx_out_off(struct specialix_board *bp, |
279 | unsigned char val) | 253 | unsigned short reg, unsigned char val) |
280 | { | 254 | { |
281 | bp->reg = reg; | 255 | bp->reg = reg; |
282 | outb (reg, bp->base + SX_ADDR_REG); | 256 | outb(reg, bp->base + SX_ADDR_REG); |
283 | outb (val, bp->base + SX_DATA_REG); | 257 | outb(val, bp->base + SX_DATA_REG); |
284 | } | 258 | } |
285 | 259 | ||
286 | 260 | ||
287 | /* Wait for Channel Command Register ready */ | 261 | /* Wait for Channel Command Register ready */ |
288 | static inline void sx_wait_CCR(struct specialix_board * bp) | 262 | static void sx_wait_CCR(struct specialix_board *bp) |
289 | { | 263 | { |
290 | unsigned long delay, flags; | 264 | unsigned long delay, flags; |
291 | unsigned char ccr; | 265 | unsigned char ccr; |
@@ -296,7 +270,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) | |||
296 | spin_unlock_irqrestore(&bp->lock, flags); | 270 | spin_unlock_irqrestore(&bp->lock, flags); |
297 | if (!ccr) | 271 | if (!ccr) |
298 | return; | 272 | return; |
299 | udelay (1); | 273 | udelay(1); |
300 | } | 274 | } |
301 | 275 | ||
302 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 276 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
@@ -304,7 +278,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) | |||
304 | 278 | ||
305 | 279 | ||
306 | /* Wait for Channel Command Register ready */ | 280 | /* Wait for Channel Command Register ready */ |
307 | static inline void sx_wait_CCR_off(struct specialix_board * bp) | 281 | static void sx_wait_CCR_off(struct specialix_board *bp) |
308 | { | 282 | { |
309 | unsigned long delay; | 283 | unsigned long delay; |
310 | unsigned char crr; | 284 | unsigned char crr; |
@@ -316,7 +290,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
316 | spin_unlock_irqrestore(&bp->lock, flags); | 290 | spin_unlock_irqrestore(&bp->lock, flags); |
317 | if (!crr) | 291 | if (!crr) |
318 | return; | 292 | return; |
319 | udelay (1); | 293 | udelay(1); |
320 | } | 294 | } |
321 | 295 | ||
322 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 296 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
@@ -327,7 +301,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
327 | * specialix IO8+ IO range functions. | 301 | * specialix IO8+ IO range functions. |
328 | */ | 302 | */ |
329 | 303 | ||
330 | static inline int sx_request_io_range(struct specialix_board * bp) | 304 | static int sx_request_io_range(struct specialix_board *bp) |
331 | { | 305 | { |
332 | return request_region(bp->base, | 306 | return request_region(bp->base, |
333 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, | 307 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, |
@@ -335,15 +309,15 @@ static inline int sx_request_io_range(struct specialix_board * bp) | |||
335 | } | 309 | } |
336 | 310 | ||
337 | 311 | ||
338 | static inline void sx_release_io_range(struct specialix_board * bp) | 312 | static void sx_release_io_range(struct specialix_board *bp) |
339 | { | 313 | { |
340 | release_region(bp->base, | 314 | release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? |
341 | bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); | 315 | SX_PCI_IO_SPACE : SX_IO_SPACE); |
342 | } | 316 | } |
343 | 317 | ||
344 | 318 | ||
345 | /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ | 319 | /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ |
346 | static int sx_set_irq ( struct specialix_board *bp) | 320 | static int sx_set_irq(struct specialix_board *bp) |
347 | { | 321 | { |
348 | int virq; | 322 | int virq; |
349 | int i; | 323 | int i; |
@@ -353,15 +327,24 @@ static int sx_set_irq ( struct specialix_board *bp) | |||
353 | return 1; | 327 | return 1; |
354 | switch (bp->irq) { | 328 | switch (bp->irq) { |
355 | /* In the same order as in the docs... */ | 329 | /* In the same order as in the docs... */ |
356 | case 15: virq = 0;break; | 330 | case 15: |
357 | case 12: virq = 1;break; | 331 | virq = 0; |
358 | case 11: virq = 2;break; | 332 | break; |
359 | case 9: virq = 3;break; | 333 | case 12: |
360 | default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq); | 334 | virq = 1; |
361 | return 0; | 335 | break; |
336 | case 11: | ||
337 | virq = 2; | ||
338 | break; | ||
339 | case 9: | ||
340 | virq = 3; | ||
341 | break; | ||
342 | default:printk(KERN_ERR | ||
343 | "Speclialix: cannot set irq to %d.\n", bp->irq); | ||
344 | return 0; | ||
362 | } | 345 | } |
363 | spin_lock_irqsave(&bp->lock, flags); | 346 | spin_lock_irqsave(&bp->lock, flags); |
364 | for (i=0;i<2;i++) { | 347 | for (i = 0; i < 2; i++) { |
365 | sx_out(bp, CD186x_CAR, i); | 348 | sx_out(bp, CD186x_CAR, i); |
366 | sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); | 349 | sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); |
367 | } | 350 | } |
@@ -371,7 +354,7 @@ static int sx_set_irq ( struct specialix_board *bp) | |||
371 | 354 | ||
372 | 355 | ||
373 | /* Reset and setup CD186x chip */ | 356 | /* Reset and setup CD186x chip */ |
374 | static int sx_init_CD186x(struct specialix_board * bp) | 357 | static int sx_init_CD186x(struct specialix_board *bp) |
375 | { | 358 | { |
376 | unsigned long flags; | 359 | unsigned long flags; |
377 | int scaler; | 360 | int scaler; |
@@ -390,7 +373,7 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
390 | sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ | 373 | sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ |
391 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ | 374 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ |
392 | /* Set RegAckEn */ | 375 | /* Set RegAckEn */ |
393 | sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); | 376 | sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); |
394 | 377 | ||
395 | /* Setting up prescaler. We need 4 ticks per 1 ms */ | 378 | /* Setting up prescaler. We need 4 ticks per 1 ms */ |
396 | scaler = SX_OSCFREQ/SPECIALIX_TPS; | 379 | scaler = SX_OSCFREQ/SPECIALIX_TPS; |
@@ -399,9 +382,9 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
399 | sx_out_off(bp, CD186x_PPRL, scaler & 0xff); | 382 | sx_out_off(bp, CD186x_PPRL, scaler & 0xff); |
400 | spin_unlock_irqrestore(&bp->lock, flags); | 383 | spin_unlock_irqrestore(&bp->lock, flags); |
401 | 384 | ||
402 | if (!sx_set_irq (bp)) { | 385 | if (!sx_set_irq(bp)) { |
403 | /* Figure out how to pass this along... */ | 386 | /* Figure out how to pass this along... */ |
404 | printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq); | 387 | printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); |
405 | rv = 0; | 388 | rv = 0; |
406 | } | 389 | } |
407 | 390 | ||
@@ -410,16 +393,16 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
410 | } | 393 | } |
411 | 394 | ||
412 | 395 | ||
413 | static int read_cross_byte (struct specialix_board *bp, int reg, int bit) | 396 | static int read_cross_byte(struct specialix_board *bp, int reg, int bit) |
414 | { | 397 | { |
415 | int i; | 398 | int i; |
416 | int t; | 399 | int t; |
417 | unsigned long flags; | 400 | unsigned long flags; |
418 | 401 | ||
419 | spin_lock_irqsave(&bp->lock, flags); | 402 | spin_lock_irqsave(&bp->lock, flags); |
420 | for (i=0, t=0;i<8;i++) { | 403 | for (i = 0, t = 0; i < 8; i++) { |
421 | sx_out_off (bp, CD186x_CAR, i); | 404 | sx_out_off(bp, CD186x_CAR, i); |
422 | if (sx_in_off (bp, reg) & bit) | 405 | if (sx_in_off(bp, reg) & bit) |
423 | t |= 1 << i; | 406 | t |= 1 << i; |
424 | } | 407 | } |
425 | spin_unlock_irqrestore(&bp->lock, flags); | 408 | spin_unlock_irqrestore(&bp->lock, flags); |
@@ -428,37 +411,10 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) | |||
428 | } | 411 | } |
429 | 412 | ||
430 | 413 | ||
431 | #ifdef SPECIALIX_TIMER | ||
432 | void missed_irq (unsigned long data) | ||
433 | { | ||
434 | unsigned char irq; | ||
435 | unsigned long flags; | ||
436 | struct specialix_board *bp = (struct specialix_board *)data; | ||
437 | |||
438 | spin_lock_irqsave(&bp->lock, flags); | ||
439 | irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) & | ||
440 | (SRSR_RREQint | | ||
441 | SRSR_TREQint | | ||
442 | SRSR_MREQint); | ||
443 | spin_unlock_irqrestore(&bp->lock, flags); | ||
444 | if (irq) { | ||
445 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); | ||
446 | sx_interrupt (-1, bp); | ||
447 | } | ||
448 | mod_timer(&missed_irq_timer, jiffies + sx_poll); | ||
449 | } | ||
450 | #endif | ||
451 | |||
452 | |||
453 | |||
454 | /* Main probing routine, also sets irq. */ | 414 | /* Main probing routine, also sets irq. */ |
455 | static int sx_probe(struct specialix_board *bp) | 415 | static int sx_probe(struct specialix_board *bp) |
456 | { | 416 | { |
457 | unsigned char val1, val2; | 417 | unsigned char val1, val2; |
458 | #if 0 | ||
459 | int irqs = 0; | ||
460 | int retries; | ||
461 | #endif | ||
462 | int rev; | 418 | int rev; |
463 | int chip; | 419 | int chip; |
464 | 420 | ||
@@ -471,17 +427,18 @@ static int sx_probe(struct specialix_board *bp) | |||
471 | 427 | ||
472 | /* Are the I/O ports here ? */ | 428 | /* Are the I/O ports here ? */ |
473 | sx_out_off(bp, CD186x_PPRL, 0x5a); | 429 | sx_out_off(bp, CD186x_PPRL, 0x5a); |
474 | short_pause (); | 430 | udelay(1); |
475 | val1 = sx_in_off(bp, CD186x_PPRL); | 431 | val1 = sx_in_off(bp, CD186x_PPRL); |
476 | 432 | ||
477 | sx_out_off(bp, CD186x_PPRL, 0xa5); | 433 | sx_out_off(bp, CD186x_PPRL, 0xa5); |
478 | short_pause (); | 434 | udelay(1); |
479 | val2 = sx_in_off(bp, CD186x_PPRL); | 435 | val2 = sx_in_off(bp, CD186x_PPRL); |
480 | 436 | ||
481 | 437 | ||
482 | if ((val1 != 0x5a) || (val2 != 0xa5)) { | 438 | if (val1 != 0x5a || val2 != 0xa5) { |
483 | printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", | 439 | printk(KERN_INFO |
484 | board_No(bp), bp->base); | 440 | "sx%d: specialix IO8+ Board at 0x%03x not found.\n", |
441 | board_No(bp), bp->base); | ||
485 | sx_release_io_range(bp); | 442 | sx_release_io_range(bp); |
486 | func_exit(); | 443 | func_exit(); |
487 | return 1; | 444 | return 1; |
@@ -489,10 +446,11 @@ static int sx_probe(struct specialix_board *bp) | |||
489 | 446 | ||
490 | /* Check the DSR lines that Specialix uses as board | 447 | /* Check the DSR lines that Specialix uses as board |
491 | identification */ | 448 | identification */ |
492 | val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); | 449 | val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); |
493 | val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); | 450 | val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); |
494 | dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n", | 451 | dprintk(SX_DEBUG_INIT, |
495 | board_No(bp), val1, val2); | 452 | "sx%d: DSR lines are: %02x, rts lines are: %02x\n", |
453 | board_No(bp), val1, val2); | ||
496 | 454 | ||
497 | /* They managed to switch the bit order between the docs and | 455 | /* They managed to switch the bit order between the docs and |
498 | the IO8+ card. The new PCI card now conforms to old docs. | 456 | the IO8+ card. The new PCI card now conforms to old docs. |
@@ -500,7 +458,8 @@ static int sx_probe(struct specialix_board *bp) | |||
500 | old card. */ | 458 | old card. */ |
501 | val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; | 459 | val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; |
502 | if (val1 != val2) { | 460 | if (val1 != val2) { |
503 | printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | 461 | printk(KERN_INFO |
462 | "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | ||
504 | board_No(bp), val2, bp->base, val1); | 463 | board_No(bp), val2, bp->base, val1); |
505 | sx_release_io_range(bp); | 464 | sx_release_io_range(bp); |
506 | func_exit(); | 465 | func_exit(); |
@@ -508,47 +467,6 @@ static int sx_probe(struct specialix_board *bp) | |||
508 | } | 467 | } |
509 | 468 | ||
510 | 469 | ||
511 | #if 0 | ||
512 | /* It's time to find IRQ for this board */ | ||
513 | for (retries = 0; retries < 5 && irqs <= 0; retries++) { | ||
514 | irqs = probe_irq_on(); | ||
515 | sx_init_CD186x(bp); /* Reset CD186x chip */ | ||
516 | sx_out(bp, CD186x_CAR, 2); /* Select port 2 */ | ||
517 | sx_wait_CCR(bp); | ||
518 | sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ | ||
519 | sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ | ||
520 | msleep(50); | ||
521 | irqs = probe_irq_off(irqs); | ||
522 | |||
523 | dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); | ||
524 | dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR)); | ||
525 | dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR)); | ||
526 | dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR)); | ||
527 | dprintk (SX_DEBUG_INIT, "\n"); | ||
528 | |||
529 | /* Reset CD186x again */ | ||
530 | if (!sx_init_CD186x(bp)) { | ||
531 | /* Hmmm. This is dead code anyway. */ | ||
532 | } | ||
533 | |||
534 | dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", | ||
535 | val1, val2, val3); | ||
536 | |||
537 | } | ||
538 | |||
539 | #if 0 | ||
540 | if (irqs <= 0) { | ||
541 | printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", | ||
542 | board_No(bp), bp->base); | ||
543 | sx_release_io_range(bp); | ||
544 | func_exit(); | ||
545 | return 1; | ||
546 | } | ||
547 | #endif | ||
548 | printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs); | ||
549 | if (irqs > 0) | ||
550 | bp->irq = irqs; | ||
551 | #endif | ||
552 | /* Reset CD186x again */ | 470 | /* Reset CD186x again */ |
553 | if (!sx_init_CD186x(bp)) { | 471 | if (!sx_init_CD186x(bp)) { |
554 | sx_release_io_range(bp); | 472 | sx_release_io_range(bp); |
@@ -560,7 +478,7 @@ static int sx_probe(struct specialix_board *bp) | |||
560 | bp->flags |= SX_BOARD_PRESENT; | 478 | bp->flags |= SX_BOARD_PRESENT; |
561 | 479 | ||
562 | /* Chip revcode pkgtype | 480 | /* Chip revcode pkgtype |
563 | GFRCR SRCR bit 7 | 481 | GFRCR SRCR bit 7 |
564 | CD180 rev B 0x81 0 | 482 | CD180 rev B 0x81 0 |
565 | CD180 rev C 0x82 0 | 483 | CD180 rev C 0x82 0 |
566 | CD1864 rev A 0x82 1 | 484 | CD1864 rev A 0x82 1 |
@@ -570,24 +488,32 @@ static int sx_probe(struct specialix_board *bp) | |||
570 | */ | 488 | */ |
571 | 489 | ||
572 | switch (sx_in_off(bp, CD186x_GFRCR)) { | 490 | switch (sx_in_off(bp, CD186x_GFRCR)) { |
573 | case 0x82:chip = 1864;rev='A';break; | 491 | case 0x82: |
574 | case 0x83:chip = 1865;rev='A';break; | 492 | chip = 1864; |
575 | case 0x84:chip = 1865;rev='B';break; | 493 | rev = 'A'; |
576 | case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */ | 494 | break; |
577 | default:chip=-1;rev='x'; | 495 | case 0x83: |
496 | chip = 1865; | ||
497 | rev = 'A'; | ||
498 | break; | ||
499 | case 0x84: | ||
500 | chip = 1865; | ||
501 | rev = 'B'; | ||
502 | break; | ||
503 | case 0x85: | ||
504 | chip = 1865; | ||
505 | rev = 'C'; | ||
506 | break; /* Does not exist at this time */ | ||
507 | default: | ||
508 | chip = -1; | ||
509 | rev = 'x'; | ||
578 | } | 510 | } |
579 | 511 | ||
580 | dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); | 512 | dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); |
581 | |||
582 | #ifdef SPECIALIX_TIMER | ||
583 | setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); | ||
584 | mod_timer(&missed_irq_timer, jiffies + sx_poll); | ||
585 | #endif | ||
586 | 513 | ||
587 | printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", | 514 | printk(KERN_INFO |
588 | board_No(bp), | 515 | "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", |
589 | bp->base, bp->irq, | 516 | board_No(bp), bp->base, bp->irq, chip, rev); |
590 | chip, rev); | ||
591 | 517 | ||
592 | func_exit(); | 518 | func_exit(); |
593 | return 0; | 519 | return 0; |
@@ -598,20 +524,22 @@ static int sx_probe(struct specialix_board *bp) | |||
598 | * Interrupt processing routines. | 524 | * Interrupt processing routines. |
599 | * */ | 525 | * */ |
600 | 526 | ||
601 | static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | 527 | static struct specialix_port *sx_get_port(struct specialix_board *bp, |
602 | unsigned char const * what) | 528 | unsigned char const *what) |
603 | { | 529 | { |
604 | unsigned char channel; | 530 | unsigned char channel; |
605 | struct specialix_port * port = NULL; | 531 | struct specialix_port *port = NULL; |
606 | 532 | ||
607 | channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; | 533 | channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; |
608 | dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel); | 534 | dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); |
609 | if (channel < CD186x_NCH) { | 535 | if (channel < CD186x_NCH) { |
610 | port = &sx_port[board_No(bp) * SX_NPORT + channel]; | 536 | port = &sx_port[board_No(bp) * SX_NPORT + channel]; |
611 | dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel, port, port->port.flags & ASYNC_INITIALIZED); | 537 | dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", |
538 | board_No(bp) * SX_NPORT + channel, port, | ||
539 | port->port.flags & ASYNC_INITIALIZED); | ||
612 | 540 | ||
613 | if (port->port.flags & ASYNC_INITIALIZED) { | 541 | if (port->port.flags & ASYNC_INITIALIZED) { |
614 | dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port); | 542 | dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); |
615 | func_exit(); | 543 | func_exit(); |
616 | return port; | 544 | return port; |
617 | } | 545 | } |
@@ -622,7 +550,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | |||
622 | } | 550 | } |
623 | 551 | ||
624 | 552 | ||
625 | static inline void sx_receive_exc(struct specialix_board * bp) | 553 | static void sx_receive_exc(struct specialix_board *bp) |
626 | { | 554 | { |
627 | struct specialix_port *port; | 555 | struct specialix_port *port; |
628 | struct tty_struct *tty; | 556 | struct tty_struct *tty; |
@@ -633,7 +561,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
633 | 561 | ||
634 | port = sx_get_port(bp, "Receive"); | 562 | port = sx_get_port(bp, "Receive"); |
635 | if (!port) { | 563 | if (!port) { |
636 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | 564 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); |
637 | func_exit(); | 565 | func_exit(); |
638 | return; | 566 | return; |
639 | } | 567 | } |
@@ -641,19 +569,21 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
641 | 569 | ||
642 | status = sx_in(bp, CD186x_RCSR); | 570 | status = sx_in(bp, CD186x_RCSR); |
643 | 571 | ||
644 | dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); | 572 | dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); |
645 | if (status & RCSR_OE) { | 573 | if (status & RCSR_OE) { |
646 | port->overrun++; | 574 | port->overrun++; |
647 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n", | 575 | dprintk(SX_DEBUG_FIFO, |
648 | board_No(bp), port_No(port), port->overrun); | 576 | "sx%d: port %d: Overrun. Total %ld overruns.\n", |
577 | board_No(bp), port_No(port), port->overrun); | ||
649 | } | 578 | } |
650 | status &= port->mark_mask; | 579 | status &= port->mark_mask; |
651 | 580 | ||
652 | /* This flip buffer check needs to be below the reading of the | 581 | /* This flip buffer check needs to be below the reading of the |
653 | status register to reset the chip's IRQ.... */ | 582 | status register to reset the chip's IRQ.... */ |
654 | if (tty_buffer_request_room(tty, 1) == 0) { | 583 | if (tty_buffer_request_room(tty, 1) == 0) { |
655 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n", | 584 | dprintk(SX_DEBUG_FIFO, |
656 | board_No(bp), port_No(port)); | 585 | "sx%d: port %d: Working around flip buffer overflow.\n", |
586 | board_No(bp), port_No(port)); | ||
657 | func_exit(); | 587 | func_exit(); |
658 | return; | 588 | return; |
659 | } | 589 | } |
@@ -664,8 +594,9 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
664 | return; | 594 | return; |
665 | } | 595 | } |
666 | if (status & RCSR_TOUT) { | 596 | if (status & RCSR_TOUT) { |
667 | printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", | 597 | printk(KERN_INFO |
668 | board_No(bp), port_No(port)); | 598 | "sx%d: port %d: Receiver timeout. Hardware problems ?\n", |
599 | board_No(bp), port_No(port)); | ||
669 | func_exit(); | 600 | func_exit(); |
670 | return; | 601 | return; |
671 | 602 | ||
@@ -688,13 +619,13 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
688 | else | 619 | else |
689 | flag = TTY_NORMAL; | 620 | flag = TTY_NORMAL; |
690 | 621 | ||
691 | if(tty_insert_flip_char(tty, ch, flag)) | 622 | if (tty_insert_flip_char(tty, ch, flag)) |
692 | tty_flip_buffer_push(tty); | 623 | tty_flip_buffer_push(tty); |
693 | func_exit(); | 624 | func_exit(); |
694 | } | 625 | } |
695 | 626 | ||
696 | 627 | ||
697 | static inline void sx_receive(struct specialix_board * bp) | 628 | static void sx_receive(struct specialix_board *bp) |
698 | { | 629 | { |
699 | struct specialix_port *port; | 630 | struct specialix_port *port; |
700 | struct tty_struct *tty; | 631 | struct tty_struct *tty; |
@@ -702,15 +633,16 @@ static inline void sx_receive(struct specialix_board * bp) | |||
702 | 633 | ||
703 | func_enter(); | 634 | func_enter(); |
704 | 635 | ||
705 | if (!(port = sx_get_port(bp, "Receive"))) { | 636 | port = sx_get_port(bp, "Receive"); |
706 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | 637 | if (port == NULL) { |
638 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | ||
707 | func_exit(); | 639 | func_exit(); |
708 | return; | 640 | return; |
709 | } | 641 | } |
710 | tty = port->port.tty; | 642 | tty = port->port.tty; |
711 | 643 | ||
712 | count = sx_in(bp, CD186x_RDCR); | 644 | count = sx_in(bp, CD186x_RDCR); |
713 | dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | 645 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); |
714 | port->hits[count > 8 ? 9 : count]++; | 646 | port->hits[count > 8 ? 9 : count]++; |
715 | 647 | ||
716 | tty_buffer_request_room(tty, count); | 648 | tty_buffer_request_room(tty, count); |
@@ -722,18 +654,19 @@ static inline void sx_receive(struct specialix_board * bp) | |||
722 | } | 654 | } |
723 | 655 | ||
724 | 656 | ||
725 | static inline void sx_transmit(struct specialix_board * bp) | 657 | static void sx_transmit(struct specialix_board *bp) |
726 | { | 658 | { |
727 | struct specialix_port *port; | 659 | struct specialix_port *port; |
728 | struct tty_struct *tty; | 660 | struct tty_struct *tty; |
729 | unsigned char count; | 661 | unsigned char count; |
730 | 662 | ||
731 | func_enter(); | 663 | func_enter(); |
732 | if (!(port = sx_get_port(bp, "Transmit"))) { | 664 | port = sx_get_port(bp, "Transmit"); |
665 | if (port == NULL) { | ||
733 | func_exit(); | 666 | func_exit(); |
734 | return; | 667 | return; |
735 | } | 668 | } |
736 | dprintk (SX_DEBUG_TX, "port: %p\n", port); | 669 | dprintk(SX_DEBUG_TX, "port: %p\n", port); |
737 | tty = port->port.tty; | 670 | tty = port->port.tty; |
738 | 671 | ||
739 | if (port->IER & IER_TXEMPTY) { | 672 | if (port->IER & IER_TXEMPTY) { |
@@ -765,7 +698,8 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
765 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | 698 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); |
766 | sx_out(bp, CD186x_TDR, CD186x_C_DELAY); | 699 | sx_out(bp, CD186x_TDR, CD186x_C_DELAY); |
767 | sx_out(bp, CD186x_TDR, count); | 700 | sx_out(bp, CD186x_TDR, count); |
768 | if (!(port->break_length -= count)) | 701 | port->break_length -= count; |
702 | if (port->break_length == 0) | ||
769 | port->break_length--; | 703 | port->break_length--; |
770 | } else { | 704 | } else { |
771 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | 705 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); |
@@ -794,36 +728,36 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
794 | sx_out(bp, CD186x_IER, port->IER); | 728 | sx_out(bp, CD186x_IER, port->IER); |
795 | } | 729 | } |
796 | if (port->xmit_cnt <= port->wakeup_chars) | 730 | if (port->xmit_cnt <= port->wakeup_chars) |
797 | tty_wakeup(tty); | 731 | tty_wakeup(tty); |
798 | 732 | ||
799 | func_exit(); | 733 | func_exit(); |
800 | } | 734 | } |
801 | 735 | ||
802 | 736 | ||
803 | static inline void sx_check_modem(struct specialix_board * bp) | 737 | static void sx_check_modem(struct specialix_board *bp) |
804 | { | 738 | { |
805 | struct specialix_port *port; | 739 | struct specialix_port *port; |
806 | struct tty_struct *tty; | 740 | struct tty_struct *tty; |
807 | unsigned char mcr; | 741 | unsigned char mcr; |
808 | int msvr_cd; | 742 | int msvr_cd; |
809 | 743 | ||
810 | dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); | 744 | dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); |
811 | if (!(port = sx_get_port(bp, "Modem"))) | 745 | port = sx_get_port(bp, "Modem"); |
746 | if (port == NULL) | ||
812 | return; | 747 | return; |
813 | 748 | ||
814 | tty = port->port.tty; | 749 | tty = port->port.tty; |
815 | 750 | ||
816 | mcr = sx_in(bp, CD186x_MCR); | 751 | mcr = sx_in(bp, CD186x_MCR); |
817 | printk ("mcr = %02x.\n", mcr); | ||
818 | 752 | ||
819 | if ((mcr & MCR_CDCHG)) { | 753 | if ((mcr & MCR_CDCHG)) { |
820 | dprintk (SX_DEBUG_SIGNALS, "CD just changed... "); | 754 | dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); |
821 | msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; | 755 | msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; |
822 | if (msvr_cd) { | 756 | if (msvr_cd) { |
823 | dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); | 757 | dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); |
824 | wake_up_interruptible(&port->port.open_wait); | 758 | wake_up_interruptible(&port->port.open_wait); |
825 | } else { | 759 | } else { |
826 | dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); | 760 | dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); |
827 | tty_hangup(tty); | 761 | tty_hangup(tty); |
828 | } | 762 | } |
829 | } | 763 | } |
@@ -874,9 +808,12 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
874 | 808 | ||
875 | spin_lock_irqsave(&bp->lock, flags); | 809 | spin_lock_irqsave(&bp->lock, flags); |
876 | 810 | ||
877 | dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | 811 | dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, |
812 | port_No(sx_get_port(bp, "INT")), | ||
813 | SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | ||
878 | if (!(bp->flags & SX_BOARD_ACTIVE)) { | 814 | if (!(bp->flags & SX_BOARD_ACTIVE)) { |
879 | dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq); | 815 | dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", |
816 | bp->irq); | ||
880 | spin_unlock_irqrestore(&bp->lock, flags); | 817 | spin_unlock_irqrestore(&bp->lock, flags); |
881 | func_exit(); | 818 | func_exit(); |
882 | return IRQ_NONE; | 819 | return IRQ_NONE; |
@@ -884,10 +821,11 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
884 | 821 | ||
885 | saved_reg = bp->reg; | 822 | saved_reg = bp->reg; |
886 | 823 | ||
887 | while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & | 824 | while (++loop < 16) { |
888 | (SRSR_RREQint | | 825 | status = sx_in(bp, CD186x_SRSR) & |
889 | SRSR_TREQint | | 826 | (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); |
890 | SRSR_MREQint)))) { | 827 | if (status == 0) |
828 | break; | ||
891 | if (status & SRSR_RREQint) { | 829 | if (status & SRSR_RREQint) { |
892 | ack = sx_in(bp, CD186x_RRAR); | 830 | ack = sx_in(bp, CD186x_RRAR); |
893 | 831 | ||
@@ -896,8 +834,9 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
896 | else if (ack == (SX_ID | GIVR_IT_REXC)) | 834 | else if (ack == (SX_ID | GIVR_IT_REXC)) |
897 | sx_receive_exc(bp); | 835 | sx_receive_exc(bp); |
898 | else | 836 | else |
899 | printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", | 837 | printk(KERN_ERR |
900 | board_No(bp), status, ack); | 838 | "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", |
839 | board_No(bp), status, ack); | ||
901 | 840 | ||
902 | } else if (status & SRSR_TREQint) { | 841 | } else if (status & SRSR_TREQint) { |
903 | ack = sx_in(bp, CD186x_TRAR); | 842 | ack = sx_in(bp, CD186x_TRAR); |
@@ -906,14 +845,16 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
906 | sx_transmit(bp); | 845 | sx_transmit(bp); |
907 | else | 846 | else |
908 | printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", | 847 | printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", |
909 | board_No(bp), status, ack, port_No (sx_get_port (bp, "Int"))); | 848 | board_No(bp), status, ack, |
849 | port_No(sx_get_port(bp, "Int"))); | ||
910 | } else if (status & SRSR_MREQint) { | 850 | } else if (status & SRSR_MREQint) { |
911 | ack = sx_in(bp, CD186x_MRAR); | 851 | ack = sx_in(bp, CD186x_MRAR); |
912 | 852 | ||
913 | if (ack == (SX_ID | GIVR_IT_MODEM)) | 853 | if (ack == (SX_ID | GIVR_IT_MODEM)) |
914 | sx_check_modem(bp); | 854 | sx_check_modem(bp); |
915 | else | 855 | else |
916 | printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | 856 | printk(KERN_ERR |
857 | "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | ||
917 | board_No(bp), status, ack); | 858 | board_No(bp), status, ack); |
918 | 859 | ||
919 | } | 860 | } |
@@ -921,7 +862,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
921 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ | 862 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ |
922 | } | 863 | } |
923 | bp->reg = saved_reg; | 864 | bp->reg = saved_reg; |
924 | outb (bp->reg, bp->base + SX_ADDR_REG); | 865 | outb(bp->reg, bp->base + SX_ADDR_REG); |
925 | spin_unlock_irqrestore(&bp->lock, flags); | 866 | spin_unlock_irqrestore(&bp->lock, flags); |
926 | func_exit(); | 867 | func_exit(); |
927 | return IRQ_HANDLED; | 868 | return IRQ_HANDLED; |
@@ -932,36 +873,26 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
932 | * Routines for open & close processing. | 873 | * Routines for open & close processing. |
933 | */ | 874 | */ |
934 | 875 | ||
935 | static void turn_ints_off (struct specialix_board *bp) | 876 | static void turn_ints_off(struct specialix_board *bp) |
936 | { | 877 | { |
937 | unsigned long flags; | 878 | unsigned long flags; |
938 | 879 | ||
939 | func_enter(); | 880 | func_enter(); |
940 | if (bp->flags & SX_BOARD_IS_PCI) { | ||
941 | /* This was intended for enabeling the interrupt on the | ||
942 | * PCI card. However it seems that it's already enabled | ||
943 | * and as PCI interrupts can be shared, there is no real | ||
944 | * reason to have to turn it off. */ | ||
945 | } | ||
946 | |||
947 | spin_lock_irqsave(&bp->lock, flags); | 881 | spin_lock_irqsave(&bp->lock, flags); |
948 | (void) sx_in_off (bp, 0); /* Turn off interrupts. */ | 882 | (void) sx_in_off(bp, 0); /* Turn off interrupts. */ |
949 | spin_unlock_irqrestore(&bp->lock, flags); | 883 | spin_unlock_irqrestore(&bp->lock, flags); |
950 | 884 | ||
951 | func_exit(); | 885 | func_exit(); |
952 | } | 886 | } |
953 | 887 | ||
954 | static void turn_ints_on (struct specialix_board *bp) | 888 | static void turn_ints_on(struct specialix_board *bp) |
955 | { | 889 | { |
956 | unsigned long flags; | 890 | unsigned long flags; |
957 | 891 | ||
958 | func_enter(); | 892 | func_enter(); |
959 | 893 | ||
960 | if (bp->flags & SX_BOARD_IS_PCI) { | ||
961 | /* play with the PCI chip. See comment above. */ | ||
962 | } | ||
963 | spin_lock_irqsave(&bp->lock, flags); | 894 | spin_lock_irqsave(&bp->lock, flags); |
964 | (void) sx_in (bp, 0); /* Turn ON interrupts. */ | 895 | (void) sx_in(bp, 0); /* Turn ON interrupts. */ |
965 | spin_unlock_irqrestore(&bp->lock, flags); | 896 | spin_unlock_irqrestore(&bp->lock, flags); |
966 | 897 | ||
967 | func_exit(); | 898 | func_exit(); |
@@ -969,7 +900,7 @@ static void turn_ints_on (struct specialix_board *bp) | |||
969 | 900 | ||
970 | 901 | ||
971 | /* Called with disabled interrupts */ | 902 | /* Called with disabled interrupts */ |
972 | static inline int sx_setup_board(struct specialix_board * bp) | 903 | static int sx_setup_board(struct specialix_board *bp) |
973 | { | 904 | { |
974 | int error; | 905 | int error; |
975 | 906 | ||
@@ -977,14 +908,16 @@ static inline int sx_setup_board(struct specialix_board * bp) | |||
977 | return 0; | 908 | return 0; |
978 | 909 | ||
979 | if (bp->flags & SX_BOARD_IS_PCI) | 910 | if (bp->flags & SX_BOARD_IS_PCI) |
980 | error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); | 911 | error = request_irq(bp->irq, sx_interrupt, |
912 | IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); | ||
981 | else | 913 | else |
982 | error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp); | 914 | error = request_irq(bp->irq, sx_interrupt, |
915 | IRQF_DISABLED, "specialix IO8+", bp); | ||
983 | 916 | ||
984 | if (error) | 917 | if (error) |
985 | return error; | 918 | return error; |
986 | 919 | ||
987 | turn_ints_on (bp); | 920 | turn_ints_on(bp); |
988 | bp->flags |= SX_BOARD_ACTIVE; | 921 | bp->flags |= SX_BOARD_ACTIVE; |
989 | 922 | ||
990 | return 0; | 923 | return 0; |
@@ -992,7 +925,7 @@ static inline int sx_setup_board(struct specialix_board * bp) | |||
992 | 925 | ||
993 | 926 | ||
994 | /* Called with disabled interrupts */ | 927 | /* Called with disabled interrupts */ |
995 | static inline void sx_shutdown_board(struct specialix_board *bp) | 928 | static void sx_shutdown_board(struct specialix_board *bp) |
996 | { | 929 | { |
997 | func_enter(); | 930 | func_enter(); |
998 | 931 | ||
@@ -1003,22 +936,26 @@ static inline void sx_shutdown_board(struct specialix_board *bp) | |||
1003 | 936 | ||
1004 | bp->flags &= ~SX_BOARD_ACTIVE; | 937 | bp->flags &= ~SX_BOARD_ACTIVE; |
1005 | 938 | ||
1006 | dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", | 939 | dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", |
1007 | bp->irq, board_No (bp)); | 940 | bp->irq, board_No(bp)); |
1008 | free_irq(bp->irq, bp); | 941 | free_irq(bp->irq, bp); |
1009 | 942 | turn_ints_off(bp); | |
1010 | turn_ints_off (bp); | ||
1011 | |||
1012 | |||
1013 | func_exit(); | 943 | func_exit(); |
1014 | } | 944 | } |
1015 | 945 | ||
946 | static unsigned int sx_crtscts(struct tty_struct *tty) | ||
947 | { | ||
948 | if (sx_rtscts) | ||
949 | return C_CRTSCTS(tty); | ||
950 | return 1; | ||
951 | } | ||
1016 | 952 | ||
1017 | /* | 953 | /* |
1018 | * Setting up port characteristics. | 954 | * Setting up port characteristics. |
1019 | * Must be called with disabled interrupts | 955 | * Must be called with disabled interrupts |
1020 | */ | 956 | */ |
1021 | static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) | 957 | static void sx_change_speed(struct specialix_board *bp, |
958 | struct specialix_port *port) | ||
1022 | { | 959 | { |
1023 | struct tty_struct *tty; | 960 | struct tty_struct *tty; |
1024 | unsigned long baud; | 961 | unsigned long baud; |
@@ -1030,7 +967,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1030 | 967 | ||
1031 | func_enter(); | 968 | func_enter(); |
1032 | 969 | ||
1033 | if (!(tty = port->port.tty) || !tty->termios) { | 970 | tty = port->port.tty; |
971 | if (!tty || !tty->termios) { | ||
1034 | func_exit(); | 972 | func_exit(); |
1035 | return; | 973 | return; |
1036 | } | 974 | } |
@@ -1043,12 +981,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1043 | 981 | ||
1044 | /* The Specialix board doens't implement the RTS lines. | 982 | /* The Specialix board doens't implement the RTS lines. |
1045 | They are used to set the IRQ level. Don't touch them. */ | 983 | They are used to set the IRQ level. Don't touch them. */ |
1046 | if (SX_CRTSCTS(tty)) | 984 | if (sx_crtscts(tty)) |
1047 | port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | 985 | port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); |
1048 | else | 986 | else |
1049 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | 987 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); |
1050 | spin_unlock_irqrestore(&bp->lock, flags); | 988 | spin_unlock_irqrestore(&bp->lock, flags); |
1051 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); | 989 | dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); |
1052 | baud = tty_get_baud_rate(tty); | 990 | baud = tty_get_baud_rate(tty); |
1053 | 991 | ||
1054 | if (baud == 38400) { | 992 | if (baud == 38400) { |
@@ -1060,21 +998,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1060 | 998 | ||
1061 | if (!baud) { | 999 | if (!baud) { |
1062 | /* Drop DTR & exit */ | 1000 | /* Drop DTR & exit */ |
1063 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); | 1001 | dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); |
1064 | if (!SX_CRTSCTS (tty)) { | 1002 | if (!sx_crtscts(tty)) { |
1065 | port -> MSVR &= ~ MSVR_DTR; | 1003 | port->MSVR &= ~MSVR_DTR; |
1066 | spin_lock_irqsave(&bp->lock, flags); | 1004 | spin_lock_irqsave(&bp->lock, flags); |
1067 | sx_out(bp, CD186x_MSVR, port->MSVR ); | 1005 | sx_out(bp, CD186x_MSVR, port->MSVR); |
1068 | spin_unlock_irqrestore(&bp->lock, flags); | 1006 | spin_unlock_irqrestore(&bp->lock, flags); |
1069 | } | 1007 | } else |
1070 | else | 1008 | dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); |
1071 | dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); | ||
1072 | return; | 1009 | return; |
1073 | } else { | 1010 | } else { |
1074 | /* Set DTR on */ | 1011 | /* Set DTR on */ |
1075 | if (!SX_CRTSCTS (tty)) { | 1012 | if (!sx_crtscts(tty)) |
1076 | port ->MSVR |= MSVR_DTR; | 1013 | port->MSVR |= MSVR_DTR; |
1077 | } | ||
1078 | } | 1014 | } |
1079 | 1015 | ||
1080 | /* | 1016 | /* |
@@ -1083,28 +1019,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1083 | 1019 | ||
1084 | /* Set baud rate for port */ | 1020 | /* Set baud rate for port */ |
1085 | tmp = port->custom_divisor ; | 1021 | tmp = port->custom_divisor ; |
1086 | if ( tmp ) | 1022 | if (tmp) |
1087 | printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n" | 1023 | printk(KERN_INFO |
1088 | "This is an untested option, please be carefull.\n", | 1024 | "sx%d: Using custom baud rate divisor %ld. \n" |
1089 | port_No (port), tmp); | 1025 | "This is an untested option, please be careful.\n", |
1026 | port_No(port), tmp); | ||
1090 | else | 1027 | else |
1091 | tmp = (((SX_OSCFREQ + baud/2) / baud + | 1028 | tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / |
1092 | CD186x_TPC/2) / CD186x_TPC); | 1029 | CD186x_TPC); |
1093 | 1030 | ||
1094 | if ((tmp < 0x10) && time_before(again, jiffies)) { | 1031 | if (tmp < 0x10 && time_before(again, jiffies)) { |
1095 | again = jiffies + HZ * 60; | 1032 | again = jiffies + HZ * 60; |
1096 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ | 1033 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ |
1097 | if (tmp >= 12) { | 1034 | if (tmp >= 12) { |
1098 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | 1035 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" |
1099 | "Performance degradation is possible.\n" | 1036 | "Performance degradation is possible.\n" |
1100 | "Read specialix.txt for more info.\n", | 1037 | "Read specialix.txt for more info.\n", |
1101 | port_No (port), tmp); | 1038 | port_No(port), tmp); |
1102 | } else { | 1039 | } else { |
1103 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | 1040 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" |
1104 | "Warning: overstressing Cirrus chip. " | 1041 | "Warning: overstressing Cirrus chip. This might not work.\n" |
1105 | "This might not work.\n" | 1042 | "Read specialix.txt for more info.\n", port_No(port), tmp); |
1106 | "Read specialix.txt for more info.\n", | ||
1107 | port_No (port), tmp); | ||
1108 | } | 1043 | } |
1109 | } | 1044 | } |
1110 | spin_lock_irqsave(&bp->lock, flags); | 1045 | spin_lock_irqsave(&bp->lock, flags); |
@@ -1114,7 +1049,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1114 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | 1049 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); |
1115 | spin_unlock_irqrestore(&bp->lock, flags); | 1050 | spin_unlock_irqrestore(&bp->lock, flags); |
1116 | if (port->custom_divisor) | 1051 | if (port->custom_divisor) |
1117 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; | 1052 | baud = (SX_OSCFREQ + port->custom_divisor/2) / |
1053 | port->custom_divisor; | ||
1118 | baud = (baud + 5) / 10; /* Estimated CPS */ | 1054 | baud = (baud + 5) / 10; /* Estimated CPS */ |
1119 | 1055 | ||
1120 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | 1056 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ |
@@ -1129,16 +1065,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1129 | sx_out(bp, CD186x_RTPR, tmp); | 1065 | sx_out(bp, CD186x_RTPR, tmp); |
1130 | spin_unlock_irqrestore(&bp->lock, flags); | 1066 | spin_unlock_irqrestore(&bp->lock, flags); |
1131 | switch (C_CSIZE(tty)) { | 1067 | switch (C_CSIZE(tty)) { |
1132 | case CS5: | 1068 | case CS5: |
1133 | cor1 |= COR1_5BITS; | 1069 | cor1 |= COR1_5BITS; |
1134 | break; | 1070 | break; |
1135 | case CS6: | 1071 | case CS6: |
1136 | cor1 |= COR1_6BITS; | 1072 | cor1 |= COR1_6BITS; |
1137 | break; | 1073 | break; |
1138 | case CS7: | 1074 | case CS7: |
1139 | cor1 |= COR1_7BITS; | 1075 | cor1 |= COR1_7BITS; |
1140 | break; | 1076 | break; |
1141 | case CS8: | 1077 | case CS8: |
1142 | cor1 |= COR1_8BITS; | 1078 | cor1 |= COR1_8BITS; |
1143 | break; | 1079 | break; |
1144 | } | 1080 | } |
@@ -1175,7 +1111,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1175 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; | 1111 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; |
1176 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; | 1112 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; |
1177 | spin_lock_irqsave(&bp->lock, flags); | 1113 | spin_lock_irqsave(&bp->lock, flags); |
1178 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); | 1114 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & |
1115 | (MSVR_CTS|MSVR_DSR)); | ||
1179 | spin_unlock_irqrestore(&bp->lock, flags); | 1116 | spin_unlock_irqrestore(&bp->lock, flags); |
1180 | #else | 1117 | #else |
1181 | port->COR2 |= COR2_CTSAE; | 1118 | port->COR2 |= COR2_CTSAE; |
@@ -1219,7 +1156,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1219 | spin_lock_irqsave(&bp->lock, flags); | 1156 | spin_lock_irqsave(&bp->lock, flags); |
1220 | sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); | 1157 | sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); |
1221 | /* Setting up modem option registers */ | 1158 | /* Setting up modem option registers */ |
1222 | dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2); | 1159 | dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", |
1160 | mcor1, mcor2); | ||
1223 | sx_out(bp, CD186x_MCOR1, mcor1); | 1161 | sx_out(bp, CD186x_MCOR1, mcor1); |
1224 | sx_out(bp, CD186x_MCOR2, mcor2); | 1162 | sx_out(bp, CD186x_MCOR2, mcor2); |
1225 | spin_unlock_irqrestore(&bp->lock, flags); | 1163 | spin_unlock_irqrestore(&bp->lock, flags); |
@@ -1238,7 +1176,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1238 | 1176 | ||
1239 | 1177 | ||
1240 | /* Must be called with interrupts enabled */ | 1178 | /* Must be called with interrupts enabled */ |
1241 | static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port) | 1179 | static int sx_setup_port(struct specialix_board *bp, |
1180 | struct specialix_port *port) | ||
1242 | { | 1181 | { |
1243 | unsigned long flags; | 1182 | unsigned long flags; |
1244 | 1183 | ||
@@ -1253,7 +1192,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
1253 | /* We may sleep in get_zeroed_page() */ | 1192 | /* We may sleep in get_zeroed_page() */ |
1254 | unsigned long tmp; | 1193 | unsigned long tmp; |
1255 | 1194 | ||
1256 | if (!(tmp = get_zeroed_page(GFP_KERNEL))) { | 1195 | tmp = get_zeroed_page(GFP_KERNEL); |
1196 | if (tmp == 0L) { | ||
1257 | func_exit(); | 1197 | func_exit(); |
1258 | return -ENOMEM; | 1198 | return -ENOMEM; |
1259 | } | 1199 | } |
@@ -1284,7 +1224,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
1284 | 1224 | ||
1285 | 1225 | ||
1286 | /* Must be called with interrupts disabled */ | 1226 | /* Must be called with interrupts disabled */ |
1287 | static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port) | 1227 | static void sx_shutdown_port(struct specialix_board *bp, |
1228 | struct specialix_port *port) | ||
1288 | { | 1229 | { |
1289 | struct tty_struct *tty; | 1230 | struct tty_struct *tty; |
1290 | int i; | 1231 | int i; |
@@ -1298,11 +1239,11 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
1298 | } | 1239 | } |
1299 | 1240 | ||
1300 | if (sx_debug & SX_DEBUG_FIFO) { | 1241 | if (sx_debug & SX_DEBUG_FIFO) { |
1301 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", | 1242 | dprintk(SX_DEBUG_FIFO, |
1302 | board_No(bp), port_No(port), port->overrun); | 1243 | "sx%d: port %d: %ld overruns, FIFO hits [ ", |
1303 | for (i = 0; i < 10; i++) { | 1244 | board_No(bp), port_No(port), port->overrun); |
1245 | for (i = 0; i < 10; i++) | ||
1304 | dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); | 1246 | dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); |
1305 | } | ||
1306 | dprintk(SX_DEBUG_FIFO, "].\n"); | 1247 | dprintk(SX_DEBUG_FIFO, "].\n"); |
1307 | } | 1248 | } |
1308 | 1249 | ||
@@ -1315,7 +1256,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
1315 | spin_lock_irqsave(&bp->lock, flags); | 1256 | spin_lock_irqsave(&bp->lock, flags); |
1316 | sx_out(bp, CD186x_CAR, port_No(port)); | 1257 | sx_out(bp, CD186x_CAR, port_No(port)); |
1317 | 1258 | ||
1318 | if (!(tty = port->port.tty) || C_HUPCL(tty)) { | 1259 | tty = port->port.tty; |
1260 | if (tty == NULL || C_HUPCL(tty)) { | ||
1319 | /* Drop DTR */ | 1261 | /* Drop DTR */ |
1320 | sx_out(bp, CD186x_MSVDTR, 0); | 1262 | sx_out(bp, CD186x_MSVDTR, 0); |
1321 | } | 1263 | } |
@@ -1338,8 +1280,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
1338 | } | 1280 | } |
1339 | 1281 | ||
1340 | 1282 | ||
1341 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | 1283 | static int block_til_ready(struct tty_struct *tty, struct file *filp, |
1342 | struct specialix_port *port) | 1284 | struct specialix_port *port) |
1343 | { | 1285 | { |
1344 | DECLARE_WAITQUEUE(wait, current); | 1286 | DECLARE_WAITQUEUE(wait, current); |
1345 | struct specialix_board *bp = port_Board(port); | 1287 | struct specialix_board *bp = port_Board(port); |
@@ -1389,23 +1331,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1389 | retval = 0; | 1331 | retval = 0; |
1390 | add_wait_queue(&port->port.open_wait, &wait); | 1332 | add_wait_queue(&port->port.open_wait, &wait); |
1391 | spin_lock_irqsave(&port->lock, flags); | 1333 | spin_lock_irqsave(&port->lock, flags); |
1392 | if (!tty_hung_up_p(filp)) { | 1334 | if (!tty_hung_up_p(filp)) |
1393 | port->port.count--; | 1335 | port->port.count--; |
1394 | } | ||
1395 | spin_unlock_irqrestore(&port->lock, flags); | 1336 | spin_unlock_irqrestore(&port->lock, flags); |
1396 | port->port.blocked_open++; | 1337 | port->port.blocked_open++; |
1397 | while (1) { | 1338 | while (1) { |
1398 | spin_lock_irqsave(&bp->lock, flags); | 1339 | spin_lock_irqsave(&bp->lock, flags); |
1399 | sx_out(bp, CD186x_CAR, port_No(port)); | 1340 | sx_out(bp, CD186x_CAR, port_No(port)); |
1400 | CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; | 1341 | CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; |
1401 | if (SX_CRTSCTS (tty)) { | 1342 | if (sx_crtscts(tty)) { |
1402 | /* Activate RTS */ | 1343 | /* Activate RTS */ |
1403 | port->MSVR |= MSVR_DTR; /* WTF? */ | 1344 | port->MSVR |= MSVR_DTR; /* WTF? */ |
1404 | sx_out (bp, CD186x_MSVR, port->MSVR); | 1345 | sx_out(bp, CD186x_MSVR, port->MSVR); |
1405 | } else { | 1346 | } else { |
1406 | /* Activate DTR */ | 1347 | /* Activate DTR */ |
1407 | port->MSVR |= MSVR_DTR; | 1348 | port->MSVR |= MSVR_DTR; |
1408 | sx_out (bp, CD186x_MSVR, port->MSVR); | 1349 | sx_out(bp, CD186x_MSVR, port->MSVR); |
1409 | } | 1350 | } |
1410 | spin_unlock_irqrestore(&bp->lock, flags); | 1351 | spin_unlock_irqrestore(&bp->lock, flags); |
1411 | set_current_state(TASK_INTERRUPTIBLE); | 1352 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -1430,9 +1371,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1430 | set_current_state(TASK_RUNNING); | 1371 | set_current_state(TASK_RUNNING); |
1431 | remove_wait_queue(&port->port.open_wait, &wait); | 1372 | remove_wait_queue(&port->port.open_wait, &wait); |
1432 | spin_lock_irqsave(&port->lock, flags); | 1373 | spin_lock_irqsave(&port->lock, flags); |
1433 | if (!tty_hung_up_p(filp)) { | 1374 | if (!tty_hung_up_p(filp)) |
1434 | port->port.count++; | 1375 | port->port.count++; |
1435 | } | ||
1436 | port->port.blocked_open--; | 1376 | port->port.blocked_open--; |
1437 | spin_unlock_irqrestore(&port->lock, flags); | 1377 | spin_unlock_irqrestore(&port->lock, flags); |
1438 | if (retval) { | 1378 | if (retval) { |
@@ -1446,12 +1386,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1446 | } | 1386 | } |
1447 | 1387 | ||
1448 | 1388 | ||
1449 | static int sx_open(struct tty_struct * tty, struct file * filp) | 1389 | static int sx_open(struct tty_struct *tty, struct file *filp) |
1450 | { | 1390 | { |
1451 | int board; | 1391 | int board; |
1452 | int error; | 1392 | int error; |
1453 | struct specialix_port * port; | 1393 | struct specialix_port *port; |
1454 | struct specialix_board * bp; | 1394 | struct specialix_board *bp; |
1455 | int i; | 1395 | int i; |
1456 | unsigned long flags; | 1396 | unsigned long flags; |
1457 | 1397 | ||
@@ -1468,17 +1408,19 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
1468 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); | 1408 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); |
1469 | port->overrun = 0; | 1409 | port->overrun = 0; |
1470 | for (i = 0; i < 10; i++) | 1410 | for (i = 0; i < 10; i++) |
1471 | port->hits[i]=0; | 1411 | port->hits[i] = 0; |
1472 | 1412 | ||
1473 | dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n", | 1413 | dprintk(SX_DEBUG_OPEN, |
1474 | board, bp, port, SX_PORT(tty->index)); | 1414 | "Board = %d, bp = %p, port = %p, portno = %d.\n", |
1415 | board, bp, port, SX_PORT(tty->index)); | ||
1475 | 1416 | ||
1476 | if (sx_paranoia_check(port, tty->name, "sx_open")) { | 1417 | if (sx_paranoia_check(port, tty->name, "sx_open")) { |
1477 | func_enter(); | 1418 | func_enter(); |
1478 | return -ENODEV; | 1419 | return -ENODEV; |
1479 | } | 1420 | } |
1480 | 1421 | ||
1481 | if ((error = sx_setup_board(bp))) { | 1422 | error = sx_setup_board(bp); |
1423 | if (error) { | ||
1482 | func_exit(); | 1424 | func_exit(); |
1483 | return error; | 1425 | return error; |
1484 | } | 1426 | } |
@@ -1490,12 +1432,14 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
1490 | port->port.tty = tty; | 1432 | port->port.tty = tty; |
1491 | spin_unlock_irqrestore(&bp->lock, flags); | 1433 | spin_unlock_irqrestore(&bp->lock, flags); |
1492 | 1434 | ||
1493 | if ((error = sx_setup_port(bp, port))) { | 1435 | error = sx_setup_port(bp, port); |
1436 | if (error) { | ||
1494 | func_enter(); | 1437 | func_enter(); |
1495 | return error; | 1438 | return error; |
1496 | } | 1439 | } |
1497 | 1440 | ||
1498 | if ((error = block_til_ready(tty, filp, port))) { | 1441 | error = block_til_ready(tty, filp, port); |
1442 | if (error) { | ||
1499 | func_enter(); | 1443 | func_enter(); |
1500 | return error; | 1444 | return error; |
1501 | } | 1445 | } |
@@ -1508,7 +1452,7 @@ static void sx_flush_buffer(struct tty_struct *tty) | |||
1508 | { | 1452 | { |
1509 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1453 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1510 | unsigned long flags; | 1454 | unsigned long flags; |
1511 | struct specialix_board * bp; | 1455 | struct specialix_board *bp; |
1512 | 1456 | ||
1513 | func_enter(); | 1457 | func_enter(); |
1514 | 1458 | ||
@@ -1526,9 +1470,9 @@ static void sx_flush_buffer(struct tty_struct *tty) | |||
1526 | func_exit(); | 1470 | func_exit(); |
1527 | } | 1471 | } |
1528 | 1472 | ||
1529 | static void sx_close(struct tty_struct * tty, struct file * filp) | 1473 | static void sx_close(struct tty_struct *tty, struct file *filp) |
1530 | { | 1474 | { |
1531 | struct specialix_port *port = (struct specialix_port *) tty->driver_data; | 1475 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1532 | struct specialix_board *bp; | 1476 | struct specialix_board *bp; |
1533 | unsigned long flags; | 1477 | unsigned long flags; |
1534 | unsigned long timeout; | 1478 | unsigned long timeout; |
@@ -1547,7 +1491,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1547 | } | 1491 | } |
1548 | 1492 | ||
1549 | bp = port_Board(port); | 1493 | bp = port_Board(port); |
1550 | if ((tty->count == 1) && (port->port.count != 1)) { | 1494 | if (tty->count == 1 && port->port.count != 1) { |
1551 | printk(KERN_ERR "sx%d: sx_close: bad port count;" | 1495 | printk(KERN_ERR "sx%d: sx_close: bad port count;" |
1552 | " tty->count is 1, port count is %d\n", | 1496 | " tty->count is 1, port count is %d\n", |
1553 | board_No(bp), port->port.count); | 1497 | board_No(bp), port->port.count); |
@@ -1570,17 +1514,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1570 | */ | 1514 | */ |
1571 | tty->closing = 1; | 1515 | tty->closing = 1; |
1572 | spin_unlock_irqrestore(&port->lock, flags); | 1516 | spin_unlock_irqrestore(&port->lock, flags); |
1573 | dprintk (SX_DEBUG_OPEN, "Closing\n"); | 1517 | dprintk(SX_DEBUG_OPEN, "Closing\n"); |
1574 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | 1518 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) |
1575 | tty_wait_until_sent(tty, port->port.closing_wait); | 1519 | tty_wait_until_sent(tty, port->port.closing_wait); |
1576 | } | ||
1577 | /* | 1520 | /* |
1578 | * At this point we stop accepting input. To do this, we | 1521 | * At this point we stop accepting input. To do this, we |
1579 | * disable the receive line status interrupts, and tell the | 1522 | * disable the receive line status interrupts, and tell the |
1580 | * interrupt driver to stop checking the data ready bit in the | 1523 | * interrupt driver to stop checking the data ready bit in the |
1581 | * line status register. | 1524 | * line status register. |
1582 | */ | 1525 | */ |
1583 | dprintk (SX_DEBUG_OPEN, "Closed\n"); | 1526 | dprintk(SX_DEBUG_OPEN, "Closed\n"); |
1584 | port->IER &= ~IER_RXD; | 1527 | port->IER &= ~IER_RXD; |
1585 | if (port->port.flags & ASYNC_INITIALIZED) { | 1528 | if (port->port.flags & ASYNC_INITIALIZED) { |
1586 | port->IER &= ~IER_TXRDY; | 1529 | port->IER &= ~IER_TXRDY; |
@@ -1595,11 +1538,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1595 | * important if there is a transmit FIFO! | 1538 | * important if there is a transmit FIFO! |
1596 | */ | 1539 | */ |
1597 | timeout = jiffies+HZ; | 1540 | timeout = jiffies+HZ; |
1598 | while(port->IER & IER_TXEMPTY) { | 1541 | while (port->IER & IER_TXEMPTY) { |
1599 | set_current_state (TASK_INTERRUPTIBLE); | 1542 | set_current_state(TASK_INTERRUPTIBLE); |
1600 | msleep_interruptible(jiffies_to_msecs(port->timeout)); | 1543 | msleep_interruptible(jiffies_to_msecs(port->timeout)); |
1601 | if (time_after(jiffies, timeout)) { | 1544 | if (time_after(jiffies, timeout)) { |
1602 | printk (KERN_INFO "Timeout waiting for close\n"); | 1545 | printk(KERN_INFO "Timeout waiting for close\n"); |
1603 | break; | 1546 | break; |
1604 | } | 1547 | } |
1605 | } | 1548 | } |
@@ -1607,13 +1550,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1607 | } | 1550 | } |
1608 | 1551 | ||
1609 | if (--bp->count < 0) { | 1552 | if (--bp->count < 0) { |
1610 | printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", | 1553 | printk(KERN_ERR |
1611 | board_No(bp), bp->count, tty->index); | 1554 | "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", |
1555 | board_No(bp), bp->count, tty->index); | ||
1612 | bp->count = 0; | 1556 | bp->count = 0; |
1613 | } | 1557 | } |
1614 | if (--port->port.count < 0) { | 1558 | if (--port->port.count < 0) { |
1615 | printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n", | 1559 | printk(KERN_ERR |
1616 | board_No(bp), port_No(port), port->port.count); | 1560 | "sx%d: sx_close: bad port count for tty%d: %d\n", |
1561 | board_No(bp), port_No(port), port->port.count); | ||
1617 | port->port.count = 0; | 1562 | port->port.count = 0; |
1618 | } | 1563 | } |
1619 | 1564 | ||
@@ -1625,9 +1570,9 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1625 | port->port.tty = NULL; | 1570 | port->port.tty = NULL; |
1626 | spin_unlock_irqrestore(&port->lock, flags); | 1571 | spin_unlock_irqrestore(&port->lock, flags); |
1627 | if (port->port.blocked_open) { | 1572 | if (port->port.blocked_open) { |
1628 | if (port->port.close_delay) { | 1573 | if (port->port.close_delay) |
1629 | msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); | 1574 | msleep_interruptible( |
1630 | } | 1575 | jiffies_to_msecs(port->port.close_delay)); |
1631 | wake_up_interruptible(&port->port.open_wait); | 1576 | wake_up_interruptible(&port->port.open_wait); |
1632 | } | 1577 | } |
1633 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1578 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
@@ -1637,8 +1582,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1637 | } | 1582 | } |
1638 | 1583 | ||
1639 | 1584 | ||
1640 | static int sx_write(struct tty_struct * tty, | 1585 | static int sx_write(struct tty_struct *tty, |
1641 | const unsigned char *buf, int count) | 1586 | const unsigned char *buf, int count) |
1642 | { | 1587 | { |
1643 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1588 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1644 | struct specialix_board *bp; | 1589 | struct specialix_board *bp; |
@@ -1690,11 +1635,11 @@ static int sx_write(struct tty_struct * tty, | |||
1690 | } | 1635 | } |
1691 | 1636 | ||
1692 | 1637 | ||
1693 | static int sx_put_char(struct tty_struct * tty, unsigned char ch) | 1638 | static int sx_put_char(struct tty_struct *tty, unsigned char ch) |
1694 | { | 1639 | { |
1695 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1640 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1696 | unsigned long flags; | 1641 | unsigned long flags; |
1697 | struct specialix_board * bp; | 1642 | struct specialix_board *bp; |
1698 | 1643 | ||
1699 | func_enter(); | 1644 | func_enter(); |
1700 | 1645 | ||
@@ -1702,7 +1647,7 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
1702 | func_exit(); | 1647 | func_exit(); |
1703 | return 0; | 1648 | return 0; |
1704 | } | 1649 | } |
1705 | dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); | 1650 | dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); |
1706 | if (!port->xmit_buf) { | 1651 | if (!port->xmit_buf) { |
1707 | func_exit(); | 1652 | func_exit(); |
1708 | return 0; | 1653 | return 0; |
@@ -1710,14 +1655,15 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
1710 | bp = port_Board(port); | 1655 | bp = port_Board(port); |
1711 | spin_lock_irqsave(&port->lock, flags); | 1656 | spin_lock_irqsave(&port->lock, flags); |
1712 | 1657 | ||
1713 | dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf); | 1658 | dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", |
1714 | if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) { | 1659 | port->xmit_cnt, port->xmit_buf); |
1660 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { | ||
1715 | spin_unlock_irqrestore(&port->lock, flags); | 1661 | spin_unlock_irqrestore(&port->lock, flags); |
1716 | dprintk (SX_DEBUG_TX, "Exit size\n"); | 1662 | dprintk(SX_DEBUG_TX, "Exit size\n"); |
1717 | func_exit(); | 1663 | func_exit(); |
1718 | return 0; | 1664 | return 0; |
1719 | } | 1665 | } |
1720 | dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); | 1666 | dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); |
1721 | port->xmit_buf[port->xmit_head++] = ch; | 1667 | port->xmit_buf[port->xmit_head++] = ch; |
1722 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1668 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
1723 | port->xmit_cnt++; | 1669 | port->xmit_cnt++; |
@@ -1728,11 +1674,11 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
1728 | } | 1674 | } |
1729 | 1675 | ||
1730 | 1676 | ||
1731 | static void sx_flush_chars(struct tty_struct * tty) | 1677 | static void sx_flush_chars(struct tty_struct *tty) |
1732 | { | 1678 | { |
1733 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1679 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1734 | unsigned long flags; | 1680 | unsigned long flags; |
1735 | struct specialix_board * bp = port_Board(port); | 1681 | struct specialix_board *bp = port_Board(port); |
1736 | 1682 | ||
1737 | func_enter(); | 1683 | func_enter(); |
1738 | 1684 | ||
@@ -1755,7 +1701,7 @@ static void sx_flush_chars(struct tty_struct * tty) | |||
1755 | } | 1701 | } |
1756 | 1702 | ||
1757 | 1703 | ||
1758 | static int sx_write_room(struct tty_struct * tty) | 1704 | static int sx_write_room(struct tty_struct *tty) |
1759 | { | 1705 | { |
1760 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1706 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1761 | int ret; | 1707 | int ret; |
@@ -1790,12 +1736,10 @@ static int sx_chars_in_buffer(struct tty_struct *tty) | |||
1790 | return port->xmit_cnt; | 1736 | return port->xmit_cnt; |
1791 | } | 1737 | } |
1792 | 1738 | ||
1793 | |||
1794 | |||
1795 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) | 1739 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) |
1796 | { | 1740 | { |
1797 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1741 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1798 | struct specialix_board * bp; | 1742 | struct specialix_board *bp; |
1799 | unsigned char status; | 1743 | unsigned char status; |
1800 | unsigned int result; | 1744 | unsigned int result; |
1801 | unsigned long flags; | 1745 | unsigned long flags; |
@@ -1808,25 +1752,23 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) | |||
1808 | } | 1752 | } |
1809 | 1753 | ||
1810 | bp = port_Board(port); | 1754 | bp = port_Board(port); |
1811 | spin_lock_irqsave (&bp->lock, flags); | 1755 | spin_lock_irqsave(&bp->lock, flags); |
1812 | sx_out(bp, CD186x_CAR, port_No(port)); | 1756 | sx_out(bp, CD186x_CAR, port_No(port)); |
1813 | status = sx_in(bp, CD186x_MSVR); | 1757 | status = sx_in(bp, CD186x_MSVR); |
1814 | spin_unlock_irqrestore(&bp->lock, flags); | 1758 | spin_unlock_irqrestore(&bp->lock, flags); |
1815 | dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", | 1759 | dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", |
1816 | port_No(port), status, sx_in (bp, CD186x_CAR)); | 1760 | port_No(port), status, sx_in(bp, CD186x_CAR)); |
1817 | dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); | 1761 | dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); |
1818 | if (SX_CRTSCTS(port->port.tty)) { | 1762 | if (sx_crtscts(port->port.tty)) { |
1819 | result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ | 1763 | result = TIOCM_DTR | TIOCM_DSR |
1820 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) | 1764 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) |
1821 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1765 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
1822 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1766 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); |
1823 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | ||
1824 | } else { | 1767 | } else { |
1825 | result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ | 1768 | result = TIOCM_RTS | TIOCM_DSR |
1826 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1769 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
1827 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1770 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
1828 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1771 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); |
1829 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | ||
1830 | } | 1772 | } |
1831 | 1773 | ||
1832 | func_exit(); | 1774 | func_exit(); |
@@ -1852,24 +1794,14 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, | |||
1852 | bp = port_Board(port); | 1794 | bp = port_Board(port); |
1853 | 1795 | ||
1854 | spin_lock_irqsave(&port->lock, flags); | 1796 | spin_lock_irqsave(&port->lock, flags); |
1855 | /* if (set & TIOCM_RTS) | 1797 | if (sx_crtscts(port->port.tty)) { |
1856 | port->MSVR |= MSVR_RTS; */ | ||
1857 | /* if (set & TIOCM_DTR) | ||
1858 | port->MSVR |= MSVR_DTR; */ | ||
1859 | |||
1860 | if (SX_CRTSCTS(port->port.tty)) { | ||
1861 | if (set & TIOCM_RTS) | 1798 | if (set & TIOCM_RTS) |
1862 | port->MSVR |= MSVR_DTR; | 1799 | port->MSVR |= MSVR_DTR; |
1863 | } else { | 1800 | } else { |
1864 | if (set & TIOCM_DTR) | 1801 | if (set & TIOCM_DTR) |
1865 | port->MSVR |= MSVR_DTR; | 1802 | port->MSVR |= MSVR_DTR; |
1866 | } | 1803 | } |
1867 | 1804 | if (sx_crtscts(port->port.tty)) { | |
1868 | /* if (clear & TIOCM_RTS) | ||
1869 | port->MSVR &= ~MSVR_RTS; */ | ||
1870 | /* if (clear & TIOCM_DTR) | ||
1871 | port->MSVR &= ~MSVR_DTR; */ | ||
1872 | if (SX_CRTSCTS(port->port.tty)) { | ||
1873 | if (clear & TIOCM_RTS) | 1805 | if (clear & TIOCM_RTS) |
1874 | port->MSVR &= ~MSVR_DTR; | 1806 | port->MSVR &= ~MSVR_DTR; |
1875 | } else { | 1807 | } else { |
@@ -1886,14 +1818,17 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, | |||
1886 | } | 1818 | } |
1887 | 1819 | ||
1888 | 1820 | ||
1889 | static inline void sx_send_break(struct specialix_port * port, unsigned long length) | 1821 | static int sx_send_break(struct tty_struct *tty, int length) |
1890 | { | 1822 | { |
1823 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | ||
1891 | struct specialix_board *bp = port_Board(port); | 1824 | struct specialix_board *bp = port_Board(port); |
1892 | unsigned long flags; | 1825 | unsigned long flags; |
1893 | 1826 | ||
1894 | func_enter(); | 1827 | func_enter(); |
1828 | if (length == 0 || length == -1) | ||
1829 | return -EOPNOTSUPP; | ||
1895 | 1830 | ||
1896 | spin_lock_irqsave (&port->lock, flags); | 1831 | spin_lock_irqsave(&port->lock, flags); |
1897 | port->break_length = SPECIALIX_TPS / HZ * length; | 1832 | port->break_length = SPECIALIX_TPS / HZ * length; |
1898 | port->COR2 |= COR2_ETC; | 1833 | port->COR2 |= COR2_ETC; |
1899 | port->IER |= IER_TXRDY; | 1834 | port->IER |= IER_TXRDY; |
@@ -1902,7 +1837,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len | |||
1902 | sx_out(bp, CD186x_COR2, port->COR2); | 1837 | sx_out(bp, CD186x_COR2, port->COR2); |
1903 | sx_out(bp, CD186x_IER, port->IER); | 1838 | sx_out(bp, CD186x_IER, port->IER); |
1904 | spin_unlock_irqrestore(&bp->lock, flags); | 1839 | spin_unlock_irqrestore(&bp->lock, flags); |
1905 | spin_unlock_irqrestore (&port->lock, flags); | 1840 | spin_unlock_irqrestore(&port->lock, flags); |
1906 | sx_wait_CCR(bp); | 1841 | sx_wait_CCR(bp); |
1907 | spin_lock_irqsave(&bp->lock, flags); | 1842 | spin_lock_irqsave(&bp->lock, flags); |
1908 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); | 1843 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); |
@@ -1910,11 +1845,12 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len | |||
1910 | sx_wait_CCR(bp); | 1845 | sx_wait_CCR(bp); |
1911 | 1846 | ||
1912 | func_exit(); | 1847 | func_exit(); |
1848 | return 0; | ||
1913 | } | 1849 | } |
1914 | 1850 | ||
1915 | 1851 | ||
1916 | static inline int sx_set_serial_info(struct specialix_port * port, | 1852 | static int sx_set_serial_info(struct specialix_port *port, |
1917 | struct serial_struct __user * newinfo) | 1853 | struct serial_struct __user *newinfo) |
1918 | { | 1854 | { |
1919 | struct serial_struct tmp; | 1855 | struct serial_struct tmp; |
1920 | struct specialix_board *bp = port_Board(port); | 1856 | struct specialix_board *bp = port_Board(port); |
@@ -1943,25 +1879,25 @@ static inline int sx_set_serial_info(struct specialix_port * port, | |||
1943 | return -EPERM; | 1879 | return -EPERM; |
1944 | } | 1880 | } |
1945 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1881 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
1946 | (tmp.flags & ASYNC_USR_MASK)); | 1882 | (tmp.flags & ASYNC_USR_MASK)); |
1947 | port->custom_divisor = tmp.custom_divisor; | 1883 | port->custom_divisor = tmp.custom_divisor; |
1948 | } else { | 1884 | } else { |
1949 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | | 1885 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | |
1950 | (tmp.flags & ASYNC_FLAGS)); | 1886 | (tmp.flags & ASYNC_FLAGS)); |
1951 | port->port.close_delay = tmp.close_delay; | 1887 | port->port.close_delay = tmp.close_delay; |
1952 | port->port.closing_wait = tmp.closing_wait; | 1888 | port->port.closing_wait = tmp.closing_wait; |
1953 | port->custom_divisor = tmp.custom_divisor; | 1889 | port->custom_divisor = tmp.custom_divisor; |
1954 | } | 1890 | } |
1955 | if (change_speed) { | 1891 | if (change_speed) |
1956 | sx_change_speed(bp, port); | 1892 | sx_change_speed(bp, port); |
1957 | } | 1893 | |
1958 | func_exit(); | 1894 | func_exit(); |
1959 | unlock_kernel(); | 1895 | unlock_kernel(); |
1960 | return 0; | 1896 | return 0; |
1961 | } | 1897 | } |
1962 | 1898 | ||
1963 | 1899 | ||
1964 | static inline int sx_get_serial_info(struct specialix_port * port, | 1900 | static int sx_get_serial_info(struct specialix_port *port, |
1965 | struct serial_struct __user *retinfo) | 1901 | struct serial_struct __user *retinfo) |
1966 | { | 1902 | { |
1967 | struct serial_struct tmp; | 1903 | struct serial_struct tmp; |
@@ -1992,11 +1928,10 @@ static inline int sx_get_serial_info(struct specialix_port * port, | |||
1992 | } | 1928 | } |
1993 | 1929 | ||
1994 | 1930 | ||
1995 | static int sx_ioctl(struct tty_struct * tty, struct file * filp, | 1931 | static int sx_ioctl(struct tty_struct *tty, struct file *filp, |
1996 | unsigned int cmd, unsigned long arg) | 1932 | unsigned int cmd, unsigned long arg) |
1997 | { | 1933 | { |
1998 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1934 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1999 | int retval; | ||
2000 | void __user *argp = (void __user *)arg; | 1935 | void __user *argp = (void __user *)arg; |
2001 | 1936 | ||
2002 | func_enter(); | 1937 | func_enter(); |
@@ -2007,34 +1942,14 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
2007 | } | 1942 | } |
2008 | 1943 | ||
2009 | switch (cmd) { | 1944 | switch (cmd) { |
2010 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 1945 | case TIOCGSERIAL: |
2011 | retval = tty_check_change(tty); | ||
2012 | if (retval) { | ||
2013 | func_exit(); | ||
2014 | return retval; | ||
2015 | } | ||
2016 | tty_wait_until_sent(tty, 0); | ||
2017 | if (!arg) | ||
2018 | sx_send_break(port, HZ/4); /* 1/4 second */ | ||
2019 | return 0; | ||
2020 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
2021 | retval = tty_check_change(tty); | ||
2022 | if (retval) { | ||
2023 | func_exit(); | ||
2024 | return retval; | ||
2025 | } | ||
2026 | tty_wait_until_sent(tty, 0); | ||
2027 | sx_send_break(port, arg ? arg*(HZ/10) : HZ/4); | ||
2028 | func_exit(); | 1946 | func_exit(); |
2029 | return 0; | ||
2030 | case TIOCGSERIAL: | ||
2031 | func_exit(); | ||
2032 | return sx_get_serial_info(port, argp); | 1947 | return sx_get_serial_info(port, argp); |
2033 | case TIOCSSERIAL: | 1948 | case TIOCSSERIAL: |
2034 | func_exit(); | 1949 | func_exit(); |
2035 | return sx_set_serial_info(port, argp); | 1950 | return sx_set_serial_info(port, argp); |
2036 | default: | 1951 | default: |
2037 | func_exit(); | 1952 | func_exit(); |
2038 | return -ENOIOCTLCMD; | 1953 | return -ENOIOCTLCMD; |
2039 | } | 1954 | } |
2040 | func_exit(); | 1955 | func_exit(); |
@@ -2042,7 +1957,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
2042 | } | 1957 | } |
2043 | 1958 | ||
2044 | 1959 | ||
2045 | static void sx_throttle(struct tty_struct * tty) | 1960 | static void sx_throttle(struct tty_struct *tty) |
2046 | { | 1961 | { |
2047 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1962 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2048 | struct specialix_board *bp; | 1963 | struct specialix_board *bp; |
@@ -2058,15 +1973,16 @@ static void sx_throttle(struct tty_struct * tty) | |||
2058 | bp = port_Board(port); | 1973 | bp = port_Board(port); |
2059 | 1974 | ||
2060 | /* Use DTR instead of RTS ! */ | 1975 | /* Use DTR instead of RTS ! */ |
2061 | if (SX_CRTSCTS (tty)) | 1976 | if (sx_crtscts(tty)) |
2062 | port->MSVR &= ~MSVR_DTR; | 1977 | port->MSVR &= ~MSVR_DTR; |
2063 | else { | 1978 | else { |
2064 | /* Auch!!! I think the system shouldn't call this then. */ | 1979 | /* Auch!!! I think the system shouldn't call this then. */ |
2065 | /* Or maybe we're supposed (allowed?) to do our side of hw | 1980 | /* Or maybe we're supposed (allowed?) to do our side of hw |
2066 | handshake anyway, even when hardware handshake is off. | 1981 | handshake anyway, even when hardware handshake is off. |
2067 | When you see this in your logs, please report.... */ | 1982 | When you see this in your logs, please report.... */ |
2068 | printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", | 1983 | printk(KERN_ERR |
2069 | port_No (port)); | 1984 | "sx%d: Need to throttle, but can't (hardware hs is off)\n", |
1985 | port_No(port)); | ||
2070 | } | 1986 | } |
2071 | spin_lock_irqsave(&bp->lock, flags); | 1987 | spin_lock_irqsave(&bp->lock, flags); |
2072 | sx_out(bp, CD186x_CAR, port_No(port)); | 1988 | sx_out(bp, CD186x_CAR, port_No(port)); |
@@ -2086,7 +2002,7 @@ static void sx_throttle(struct tty_struct * tty) | |||
2086 | } | 2002 | } |
2087 | 2003 | ||
2088 | 2004 | ||
2089 | static void sx_unthrottle(struct tty_struct * tty) | 2005 | static void sx_unthrottle(struct tty_struct *tty) |
2090 | { | 2006 | { |
2091 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2007 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2092 | struct specialix_board *bp; | 2008 | struct specialix_board *bp; |
@@ -2103,9 +2019,9 @@ static void sx_unthrottle(struct tty_struct * tty) | |||
2103 | 2019 | ||
2104 | spin_lock_irqsave(&port->lock, flags); | 2020 | spin_lock_irqsave(&port->lock, flags); |
2105 | /* XXXX Use DTR INSTEAD???? */ | 2021 | /* XXXX Use DTR INSTEAD???? */ |
2106 | if (SX_CRTSCTS(tty)) { | 2022 | if (sx_crtscts(tty)) |
2107 | port->MSVR |= MSVR_DTR; | 2023 | port->MSVR |= MSVR_DTR; |
2108 | } /* Else clause: see remark in "sx_throttle"... */ | 2024 | /* Else clause: see remark in "sx_throttle"... */ |
2109 | spin_lock_irqsave(&bp->lock, flags); | 2025 | spin_lock_irqsave(&bp->lock, flags); |
2110 | sx_out(bp, CD186x_CAR, port_No(port)); | 2026 | sx_out(bp, CD186x_CAR, port_No(port)); |
2111 | spin_unlock_irqrestore(&bp->lock, flags); | 2027 | spin_unlock_irqrestore(&bp->lock, flags); |
@@ -2127,7 +2043,7 @@ static void sx_unthrottle(struct tty_struct * tty) | |||
2127 | } | 2043 | } |
2128 | 2044 | ||
2129 | 2045 | ||
2130 | static void sx_stop(struct tty_struct * tty) | 2046 | static void sx_stop(struct tty_struct *tty) |
2131 | { | 2047 | { |
2132 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2048 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2133 | struct specialix_board *bp; | 2049 | struct specialix_board *bp; |
@@ -2154,7 +2070,7 @@ static void sx_stop(struct tty_struct * tty) | |||
2154 | } | 2070 | } |
2155 | 2071 | ||
2156 | 2072 | ||
2157 | static void sx_start(struct tty_struct * tty) | 2073 | static void sx_start(struct tty_struct *tty) |
2158 | { | 2074 | { |
2159 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2075 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2160 | struct specialix_board *bp; | 2076 | struct specialix_board *bp; |
@@ -2182,7 +2098,7 @@ static void sx_start(struct tty_struct * tty) | |||
2182 | func_exit(); | 2098 | func_exit(); |
2183 | } | 2099 | } |
2184 | 2100 | ||
2185 | static void sx_hangup(struct tty_struct * tty) | 2101 | static void sx_hangup(struct tty_struct *tty) |
2186 | { | 2102 | { |
2187 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2103 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2188 | struct specialix_board *bp; | 2104 | struct specialix_board *bp; |
@@ -2201,8 +2117,9 @@ static void sx_hangup(struct tty_struct * tty) | |||
2201 | spin_lock_irqsave(&port->lock, flags); | 2117 | spin_lock_irqsave(&port->lock, flags); |
2202 | bp->count -= port->port.count; | 2118 | bp->count -= port->port.count; |
2203 | if (bp->count < 0) { | 2119 | if (bp->count < 0) { |
2204 | printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", | 2120 | printk(KERN_ERR |
2205 | board_No(bp), bp->count, tty->index); | 2121 | "sx%d: sx_hangup: bad board count: %d port: %d\n", |
2122 | board_No(bp), bp->count, tty->index); | ||
2206 | bp->count = 0; | 2123 | bp->count = 0; |
2207 | } | 2124 | } |
2208 | port->port.count = 0; | 2125 | port->port.count = 0; |
@@ -2215,11 +2132,12 @@ static void sx_hangup(struct tty_struct * tty) | |||
2215 | } | 2132 | } |
2216 | 2133 | ||
2217 | 2134 | ||
2218 | static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) | 2135 | static void sx_set_termios(struct tty_struct *tty, |
2136 | struct ktermios *old_termios) | ||
2219 | { | 2137 | { |
2220 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2138 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2221 | unsigned long flags; | 2139 | unsigned long flags; |
2222 | struct specialix_board * bp; | 2140 | struct specialix_board *bp; |
2223 | 2141 | ||
2224 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) | 2142 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) |
2225 | return; | 2143 | return; |
@@ -2254,6 +2172,7 @@ static const struct tty_operations sx_ops = { | |||
2254 | .hangup = sx_hangup, | 2172 | .hangup = sx_hangup, |
2255 | .tiocmget = sx_tiocmget, | 2173 | .tiocmget = sx_tiocmget, |
2256 | .tiocmset = sx_tiocmset, | 2174 | .tiocmset = sx_tiocmset, |
2175 | .break_ctl = sx_send_break, | ||
2257 | }; | 2176 | }; |
2258 | 2177 | ||
2259 | static int sx_init_drivers(void) | 2178 | static int sx_init_drivers(void) |
@@ -2280,13 +2199,16 @@ static int sx_init_drivers(void) | |||
2280 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 2199 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
2281 | specialix_driver->init_termios.c_ispeed = 9600; | 2200 | specialix_driver->init_termios.c_ispeed = 9600; |
2282 | specialix_driver->init_termios.c_ospeed = 9600; | 2201 | specialix_driver->init_termios.c_ospeed = 9600; |
2283 | specialix_driver->flags = TTY_DRIVER_REAL_RAW; | 2202 | specialix_driver->flags = TTY_DRIVER_REAL_RAW | |
2203 | TTY_DRIVER_HARDWARE_BREAK; | ||
2284 | tty_set_operations(specialix_driver, &sx_ops); | 2204 | tty_set_operations(specialix_driver, &sx_ops); |
2285 | 2205 | ||
2286 | if ((error = tty_register_driver(specialix_driver))) { | 2206 | error = tty_register_driver(specialix_driver); |
2207 | if (error) { | ||
2287 | put_tty_driver(specialix_driver); | 2208 | put_tty_driver(specialix_driver); |
2288 | printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", | 2209 | printk(KERN_ERR |
2289 | error); | 2210 | "sx: Couldn't register specialix IO8+ driver, error = %d\n", |
2211 | error); | ||
2290 | func_exit(); | 2212 | func_exit(); |
2291 | return 1; | 2213 | return 1; |
2292 | } | 2214 | } |
@@ -2322,11 +2244,11 @@ static int __init specialix_init(void) | |||
2322 | 2244 | ||
2323 | printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); | 2245 | printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); |
2324 | printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); | 2246 | printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); |
2325 | #ifdef CONFIG_SPECIALIX_RTSCTS | 2247 | if (sx_rtscts) |
2326 | printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); | 2248 | printk(KERN_INFO |
2327 | #else | 2249 | "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); |
2328 | printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); | 2250 | else |
2329 | #endif | 2251 | printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); |
2330 | 2252 | ||
2331 | for (i = 0; i < SX_NBOARD; i++) | 2253 | for (i = 0; i < SX_NBOARD; i++) |
2332 | spin_lock_init(&sx_board[i].lock); | 2254 | spin_lock_init(&sx_board[i].lock); |
@@ -2344,27 +2266,27 @@ static int __init specialix_init(void) | |||
2344 | { | 2266 | { |
2345 | struct pci_dev *pdev = NULL; | 2267 | struct pci_dev *pdev = NULL; |
2346 | 2268 | ||
2347 | i=0; | 2269 | i = 0; |
2348 | while (i < SX_NBOARD) { | 2270 | while (i < SX_NBOARD) { |
2349 | if (sx_board[i].flags & SX_BOARD_PRESENT) { | 2271 | if (sx_board[i].flags & SX_BOARD_PRESENT) { |
2350 | i++; | 2272 | i++; |
2351 | continue; | 2273 | continue; |
2352 | } | 2274 | } |
2353 | pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, | 2275 | pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, |
2354 | PCI_DEVICE_ID_SPECIALIX_IO8, | 2276 | PCI_DEVICE_ID_SPECIALIX_IO8, pdev); |
2355 | pdev); | 2277 | if (!pdev) |
2356 | if (!pdev) break; | 2278 | break; |
2357 | 2279 | ||
2358 | if (pci_enable_device(pdev)) | 2280 | if (pci_enable_device(pdev)) |
2359 | continue; | 2281 | continue; |
2360 | 2282 | ||
2361 | sx_board[i].irq = pdev->irq; | 2283 | sx_board[i].irq = pdev->irq; |
2362 | 2284 | ||
2363 | sx_board[i].base = pci_resource_start (pdev, 2); | 2285 | sx_board[i].base = pci_resource_start(pdev, 2); |
2364 | 2286 | ||
2365 | sx_board[i].flags |= SX_BOARD_IS_PCI; | 2287 | sx_board[i].flags |= SX_BOARD_IS_PCI; |
2366 | if (!sx_probe(&sx_board[i])) | 2288 | if (!sx_probe(&sx_board[i])) |
2367 | found ++; | 2289 | found++; |
2368 | } | 2290 | } |
2369 | /* May exit pci_get sequence early with lots of boards */ | 2291 | /* May exit pci_get sequence early with lots of boards */ |
2370 | if (pdev != NULL) | 2292 | if (pdev != NULL) |
@@ -2384,16 +2306,13 @@ static int __init specialix_init(void) | |||
2384 | } | 2306 | } |
2385 | 2307 | ||
2386 | static int iobase[SX_NBOARD] = {0,}; | 2308 | static int iobase[SX_NBOARD] = {0,}; |
2387 | 2309 | static int irq[SX_NBOARD] = {0,}; | |
2388 | static int irq [SX_NBOARD] = {0,}; | ||
2389 | 2310 | ||
2390 | module_param_array(iobase, int, NULL, 0); | 2311 | module_param_array(iobase, int, NULL, 0); |
2391 | module_param_array(irq, int, NULL, 0); | 2312 | module_param_array(irq, int, NULL, 0); |
2392 | module_param(sx_debug, int, 0); | 2313 | module_param(sx_debug, int, 0); |
2314 | module_param(sx_rtscts, int, 0); | ||
2393 | module_param(sx_rxfifo, int, 0); | 2315 | module_param(sx_rxfifo, int, 0); |
2394 | #ifdef SPECIALIX_TIMER | ||
2395 | module_param(sx_poll, int, 0); | ||
2396 | #endif | ||
2397 | 2316 | ||
2398 | /* | 2317 | /* |
2399 | * You can setup up to 4 boards. | 2318 | * You can setup up to 4 boards. |
@@ -2411,10 +2330,10 @@ static int __init specialix_init_module(void) | |||
2411 | func_enter(); | 2330 | func_enter(); |
2412 | 2331 | ||
2413 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | 2332 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { |
2414 | for(i = 0; i < SX_NBOARD; i++) { | 2333 | for (i = 0; i < SX_NBOARD; i++) { |
2415 | sx_board[i].base = iobase[i]; | 2334 | sx_board[i].base = iobase[i]; |
2416 | sx_board[i].irq = irq[i]; | 2335 | sx_board[i].irq = irq[i]; |
2417 | sx_board[i].count= 0; | 2336 | sx_board[i].count = 0; |
2418 | } | 2337 | } |
2419 | } | 2338 | } |
2420 | 2339 | ||
@@ -2433,10 +2352,6 @@ static void __exit specialix_exit_module(void) | |||
2433 | for (i = 0; i < SX_NBOARD; i++) | 2352 | for (i = 0; i < SX_NBOARD; i++) |
2434 | if (sx_board[i].flags & SX_BOARD_PRESENT) | 2353 | if (sx_board[i].flags & SX_BOARD_PRESENT) |
2435 | sx_release_io_range(&sx_board[i]); | 2354 | sx_release_io_range(&sx_board[i]); |
2436 | #ifdef SPECIALIX_TIMER | ||
2437 | del_timer_sync(&missed_irq_timer); | ||
2438 | #endif | ||
2439 | |||
2440 | func_exit(); | 2355 | func_exit(); |
2441 | } | 2356 | } |
2442 | 2357 | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0243efb0be95..19db1eb87c26 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -1025,7 +1025,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count | |||
1025 | 1025 | ||
1026 | /*****************************************************************************/ | 1026 | /*****************************************************************************/ |
1027 | 1027 | ||
1028 | static void stl_putchar(struct tty_struct *tty, unsigned char ch) | 1028 | static int stl_putchar(struct tty_struct *tty, unsigned char ch) |
1029 | { | 1029 | { |
1030 | struct stlport *portp; | 1030 | struct stlport *portp; |
1031 | unsigned int len; | 1031 | unsigned int len; |
@@ -1034,12 +1034,12 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) | |||
1034 | pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); | 1034 | pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); |
1035 | 1035 | ||
1036 | if (tty == NULL) | 1036 | if (tty == NULL) |
1037 | return; | 1037 | return -EINVAL; |
1038 | portp = tty->driver_data; | 1038 | portp = tty->driver_data; |
1039 | if (portp == NULL) | 1039 | if (portp == NULL) |
1040 | return; | 1040 | return -EINVAL; |
1041 | if (portp->tx.buf == NULL) | 1041 | if (portp->tx.buf == NULL) |
1042 | return; | 1042 | return -EINVAL; |
1043 | 1043 | ||
1044 | head = portp->tx.head; | 1044 | head = portp->tx.head; |
1045 | tail = portp->tx.tail; | 1045 | tail = portp->tx.tail; |
@@ -1053,6 +1053,7 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) | |||
1053 | head = portp->tx.buf; | 1053 | head = portp->tx.buf; |
1054 | } | 1054 | } |
1055 | portp->tx.head = head; | 1055 | portp->tx.head = head; |
1056 | return 0; | ||
1056 | } | 1057 | } |
1057 | 1058 | ||
1058 | /*****************************************************************************/ | 1059 | /*****************************************************************************/ |
@@ -1255,7 +1256,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, | |||
1255 | static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) | 1256 | static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) |
1256 | { | 1257 | { |
1257 | struct stlport *portp; | 1258 | struct stlport *portp; |
1258 | unsigned int ival; | ||
1259 | int rc; | 1259 | int rc; |
1260 | void __user *argp = (void __user *)arg; | 1260 | void __user *argp = (void __user *)arg; |
1261 | 1261 | ||
@@ -1460,19 +1460,20 @@ static void stl_hangup(struct tty_struct *tty) | |||
1460 | 1460 | ||
1461 | /*****************************************************************************/ | 1461 | /*****************************************************************************/ |
1462 | 1462 | ||
1463 | static void stl_breakctl(struct tty_struct *tty, int state) | 1463 | static int stl_breakctl(struct tty_struct *tty, int state) |
1464 | { | 1464 | { |
1465 | struct stlport *portp; | 1465 | struct stlport *portp; |
1466 | 1466 | ||
1467 | pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); | 1467 | pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); |
1468 | 1468 | ||
1469 | if (tty == NULL) | 1469 | if (tty == NULL) |
1470 | return; | 1470 | return -EINVAL; |
1471 | portp = tty->driver_data; | 1471 | portp = tty->driver_data; |
1472 | if (portp == NULL) | 1472 | if (portp == NULL) |
1473 | return; | 1473 | return -EINVAL; |
1474 | 1474 | ||
1475 | stl_sendbreak(portp, ((state == -1) ? 1 : 2)); | 1475 | stl_sendbreak(portp, ((state == -1) ? 1 : 2)); |
1476 | return 0; | ||
1476 | } | 1477 | } |
1477 | 1478 | ||
1478 | /*****************************************************************************/ | 1479 | /*****************************************************************************/ |
@@ -4753,8 +4754,8 @@ static int __init stallion_module_init(void) | |||
4753 | if (IS_ERR(stallion_class)) | 4754 | if (IS_ERR(stallion_class)) |
4754 | printk("STALLION: failed to create class\n"); | 4755 | printk("STALLION: failed to create class\n"); |
4755 | for (i = 0; i < 4; i++) | 4756 | for (i = 0; i < 4; i++) |
4756 | device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), | 4757 | device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), |
4757 | "staliomem%d", i); | 4758 | NULL, "staliomem%d", i); |
4758 | 4759 | ||
4759 | return 0; | 4760 | return 0; |
4760 | err_unrtty: | 4761 | err_unrtty: |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index d5cffcd6a572..c385206f9db5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -286,8 +286,8 @@ static void sx_close(void *ptr); | |||
286 | static int sx_chars_in_buffer(void *ptr); | 286 | static int sx_chars_in_buffer(void *ptr); |
287 | static int sx_init_board(struct sx_board *board); | 287 | static int sx_init_board(struct sx_board *board); |
288 | static int sx_init_portstructs(int nboards, int nports); | 288 | static int sx_init_portstructs(int nboards, int nports); |
289 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 289 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
290 | unsigned int cmd, unsigned long arg); | 290 | unsigned long arg); |
291 | static int sx_init_drivers(void); | 291 | static int sx_init_drivers(void); |
292 | 292 | ||
293 | static struct tty_driver *sx_driver; | 293 | static struct tty_driver *sx_driver; |
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { | |||
396 | 396 | ||
397 | static const struct file_operations sx_fw_fops = { | 397 | static const struct file_operations sx_fw_fops = { |
398 | .owner = THIS_MODULE, | 398 | .owner = THIS_MODULE, |
399 | .ioctl = sx_fw_ioctl, | 399 | .unlocked_ioctl = sx_fw_ioctl, |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static struct miscdevice sx_fw_device = { | 402 | static struct miscdevice sx_fw_device = { |
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) | |||
1686 | } | 1686 | } |
1687 | #endif | 1687 | #endif |
1688 | 1688 | ||
1689 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 1689 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
1690 | unsigned int cmd, unsigned long arg) | 1690 | unsigned long arg) |
1691 | { | 1691 | { |
1692 | int rc = 0; | 1692 | long rc = 0; |
1693 | int __user *descr = (int __user *)arg; | 1693 | int __user *descr = (int __user *)arg; |
1694 | int i; | 1694 | int i; |
1695 | static struct sx_board *board = NULL; | 1695 | static struct sx_board *board = NULL; |
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1699 | 1699 | ||
1700 | func_enter(); | 1700 | func_enter(); |
1701 | 1701 | ||
1702 | #if 0 | 1702 | if (!capable(CAP_SYS_RAWIO)) |
1703 | /* Removed superuser check: Sysops can use the permissions on the device | ||
1704 | file to restrict access. Recommendation: Root only. (root.root 600) */ | ||
1705 | if (!capable(CAP_SYS_ADMIN)) { | ||
1706 | return -EPERM; | 1703 | return -EPERM; |
1707 | } | 1704 | |
1708 | #endif | 1705 | lock_kernel(); |
1709 | 1706 | ||
1710 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1707 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
1711 | 1708 | ||
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1720 | for (i = 0; i < SX_NBOARDS; i++) | 1717 | for (i = 0; i < SX_NBOARDS; i++) |
1721 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); | 1718 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); |
1722 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); | 1719 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); |
1720 | unlock_kernel(); | ||
1723 | return -EIO; | 1721 | return -EIO; |
1724 | } | 1722 | } |
1725 | 1723 | ||
1726 | switch (cmd) { | 1724 | switch (cmd) { |
1727 | case SXIO_SET_BOARD: | 1725 | case SXIO_SET_BOARD: |
1728 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); | 1726 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); |
1727 | rc = -EIO; | ||
1729 | if (arg >= SX_NBOARDS) | 1728 | if (arg >= SX_NBOARDS) |
1730 | return -EIO; | 1729 | break; |
1731 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); | 1730 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); |
1732 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) | 1731 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) |
1733 | return -EIO; | 1732 | break; |
1734 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); | 1733 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); |
1735 | board = &boards[arg]; | 1734 | board = &boards[arg]; |
1735 | rc = 0; | ||
1736 | /* FIXME: And this does ... nothing?? */ | ||
1736 | break; | 1737 | break; |
1737 | case SXIO_GET_TYPE: | 1738 | case SXIO_GET_TYPE: |
1738 | rc = -ENOENT; /* If we manage to miss one, return error. */ | 1739 | 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, | |||
1746 | rc = SX_TYPE_SI; | 1747 | rc = SX_TYPE_SI; |
1747 | if (IS_EISA_BOARD(board)) | 1748 | if (IS_EISA_BOARD(board)) |
1748 | rc = SX_TYPE_SI; | 1749 | rc = SX_TYPE_SI; |
1749 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); | 1750 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); |
1750 | break; | 1751 | break; |
1751 | case SXIO_DO_RAMTEST: | 1752 | case SXIO_DO_RAMTEST: |
1752 | if (sx_initialized) /* Already initialized: better not ramtest the board. */ | 1753 | 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, | |||
1760 | rc = do_memtest(board, 0, 0x7ff8); | 1761 | rc = do_memtest(board, 0, 0x7ff8); |
1761 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ | 1762 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ |
1762 | } | 1763 | } |
1763 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", | 1764 | sx_dprintk(SX_DEBUG_FIRMWARE, |
1764 | rc); | 1765 | "returning memtest result= %ld\n", rc); |
1765 | break; | 1766 | break; |
1766 | case SXIO_DOWNLOAD: | 1767 | case SXIO_DOWNLOAD: |
1767 | if (sx_initialized) /* Already initialized */ | 1768 | if (sx_initialized) {/* Already initialized */ |
1768 | return -EEXIST; | 1769 | rc = -EEXIST; |
1769 | if (!sx_reset(board)) | 1770 | break; |
1770 | return -EIO; | 1771 | } |
1772 | if (!sx_reset(board)) { | ||
1773 | rc = -EIO; | ||
1774 | break; | ||
1775 | } | ||
1771 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); | 1776 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); |
1772 | 1777 | ||
1773 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); | 1778 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); |
1774 | if (!tmp) | 1779 | if (!tmp) { |
1775 | return -ENOMEM; | 1780 | rc = -ENOMEM; |
1781 | break; | ||
1782 | } | ||
1783 | /* FIXME: check returns */ | ||
1776 | get_user(nbytes, descr++); | 1784 | get_user(nbytes, descr++); |
1777 | get_user(offset, descr++); | 1785 | get_user(offset, descr++); |
1778 | get_user(data, descr++); | 1786 | get_user(data, descr++); |
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1782 | (i + SX_CHUNK_SIZE > nbytes) ? | 1790 | (i + SX_CHUNK_SIZE > nbytes) ? |
1783 | nbytes - i : SX_CHUNK_SIZE)) { | 1791 | nbytes - i : SX_CHUNK_SIZE)) { |
1784 | kfree(tmp); | 1792 | kfree(tmp); |
1785 | return -EFAULT; | 1793 | rc = -EFAULT; |
1794 | break; | ||
1786 | } | 1795 | } |
1787 | memcpy_toio(board->base2 + offset + i, tmp, | 1796 | memcpy_toio(board->base2 + offset + i, tmp, |
1788 | (i + SX_CHUNK_SIZE > nbytes) ? | 1797 | (i + SX_CHUNK_SIZE > nbytes) ? |
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1798 | rc = sx_nports; | 1807 | rc = sx_nports; |
1799 | break; | 1808 | break; |
1800 | case SXIO_INIT: | 1809 | case SXIO_INIT: |
1801 | if (sx_initialized) /* Already initialized */ | 1810 | if (sx_initialized) { /* Already initialized */ |
1802 | return -EEXIST; | 1811 | rc = -EEXIST; |
1812 | break; | ||
1813 | } | ||
1803 | /* This is not allowed until all boards are initialized... */ | 1814 | /* This is not allowed until all boards are initialized... */ |
1804 | for (i = 0; i < SX_NBOARDS; i++) { | 1815 | for (i = 0; i < SX_NBOARDS; i++) { |
1805 | if ((boards[i].flags & SX_BOARD_PRESENT) && | 1816 | if ((boards[i].flags & SX_BOARD_PRESENT) && |
1806 | !(boards[i].flags & SX_BOARD_INITIALIZED)) | 1817 | !(boards[i].flags & SX_BOARD_INITIALIZED)) { |
1807 | return -EIO; | 1818 | rc = -EIO; |
1819 | break; | ||
1820 | } | ||
1808 | } | 1821 | } |
1809 | for (i = 0; i < SX_NBOARDS; i++) | 1822 | for (i = 0; i < SX_NBOARDS; i++) |
1810 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | 1823 | if (!(boards[i].flags & SX_BOARD_PRESENT)) |
@@ -1832,15 +1845,15 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1832 | rc = sx_nports; | 1845 | rc = sx_nports; |
1833 | break; | 1846 | break; |
1834 | default: | 1847 | default: |
1835 | printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", | 1848 | rc = -ENOTTY; |
1836 | cmd); | ||
1837 | break; | 1849 | break; |
1838 | } | 1850 | } |
1851 | unlock_kernel(); | ||
1839 | func_exit(); | 1852 | func_exit(); |
1840 | return rc; | 1853 | return rc; |
1841 | } | 1854 | } |
1842 | 1855 | ||
1843 | static void sx_break(struct tty_struct *tty, int flag) | 1856 | static int sx_break(struct tty_struct *tty, int flag) |
1844 | { | 1857 | { |
1845 | struct sx_port *port = tty->driver_data; | 1858 | struct sx_port *port = tty->driver_data; |
1846 | int rv; | 1859 | int rv; |
@@ -1857,6 +1870,7 @@ static void sx_break(struct tty_struct *tty, int flag) | |||
1857 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); | 1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); |
1858 | unlock_kernel(); | 1871 | unlock_kernel(); |
1859 | func_exit(); | 1872 | func_exit(); |
1873 | return 0; | ||
1860 | } | 1874 | } |
1861 | 1875 | ||
1862 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) | 1876 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 2b9e930097e4..500f5176b6ba 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -2894,9 +2894,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
2894 | * | 2894 | * |
2895 | * Arguments: tty pointer to tty instance data | 2895 | * Arguments: tty pointer to tty instance data |
2896 | * break_state -1=set break condition, 0=clear | 2896 | * break_state -1=set break condition, 0=clear |
2897 | * Return Value: None | 2897 | * Return Value: error code |
2898 | */ | 2898 | */ |
2899 | static void mgsl_break(struct tty_struct *tty, int break_state) | 2899 | static int mgsl_break(struct tty_struct *tty, int break_state) |
2900 | { | 2900 | { |
2901 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 2901 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; |
2902 | unsigned long flags; | 2902 | unsigned long flags; |
@@ -2906,7 +2906,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) | |||
2906 | __FILE__,__LINE__, info->device_name, break_state); | 2906 | __FILE__,__LINE__, info->device_name, break_state); |
2907 | 2907 | ||
2908 | if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) | 2908 | if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) |
2909 | return; | 2909 | return -EINVAL; |
2910 | 2910 | ||
2911 | spin_lock_irqsave(&info->irq_spinlock,flags); | 2911 | spin_lock_irqsave(&info->irq_spinlock,flags); |
2912 | if (break_state == -1) | 2912 | if (break_state == -1) |
@@ -2914,6 +2914,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) | |||
2914 | else | 2914 | else |
2915 | usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); | 2915 | usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); |
2916 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 2916 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
2917 | return 0; | ||
2917 | 2918 | ||
2918 | } /* end of mgsl_break() */ | 2919 | } /* end of mgsl_break() */ |
2919 | 2920 | ||
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 88083b066261..509c89ac5bd3 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -162,7 +162,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v | |||
162 | static int chars_in_buffer(struct tty_struct *tty); | 162 | static int chars_in_buffer(struct tty_struct *tty); |
163 | static void throttle(struct tty_struct * tty); | 163 | static void throttle(struct tty_struct * tty); |
164 | static void unthrottle(struct tty_struct * tty); | 164 | static void unthrottle(struct tty_struct * tty); |
165 | static void set_break(struct tty_struct *tty, int break_state); | 165 | static int set_break(struct tty_struct *tty, int break_state); |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * generic HDLC support and callbacks | 168 | * generic HDLC support and callbacks |
@@ -211,6 +211,7 @@ struct slgt_desc | |||
211 | char *buf; /* virtual address of data buffer */ | 211 | char *buf; /* virtual address of data buffer */ |
212 | unsigned int pdesc; /* physical address of this descriptor */ | 212 | unsigned int pdesc; /* physical address of this descriptor */ |
213 | dma_addr_t buf_dma_addr; | 213 | dma_addr_t buf_dma_addr; |
214 | unsigned short buf_count; | ||
214 | }; | 215 | }; |
215 | 216 | ||
216 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) | 217 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) |
@@ -299,7 +300,7 @@ struct slgt_info { | |||
299 | u32 idle_mode; | 300 | u32 idle_mode; |
300 | u32 max_frame_size; /* as set by device config */ | 301 | u32 max_frame_size; /* as set by device config */ |
301 | 302 | ||
302 | unsigned int raw_rx_size; | 303 | unsigned int rbuf_fill_level; |
303 | unsigned int if_mode; | 304 | unsigned int if_mode; |
304 | 305 | ||
305 | /* device status */ | 306 | /* device status */ |
@@ -462,6 +463,7 @@ static void tx_start(struct slgt_info *info); | |||
462 | static void tx_stop(struct slgt_info *info); | 463 | static void tx_stop(struct slgt_info *info); |
463 | static void tx_set_idle(struct slgt_info *info); | 464 | static void tx_set_idle(struct slgt_info *info); |
464 | static unsigned int free_tbuf_count(struct slgt_info *info); | 465 | static unsigned int free_tbuf_count(struct slgt_info *info); |
466 | static unsigned int tbuf_bytes(struct slgt_info *info); | ||
465 | static void reset_tbufs(struct slgt_info *info); | 467 | static void reset_tbufs(struct slgt_info *info); |
466 | static void tdma_reset(struct slgt_info *info); | 468 | static void tdma_reset(struct slgt_info *info); |
467 | static void tdma_start(struct slgt_info *info); | 469 | static void tdma_start(struct slgt_info *info); |
@@ -509,7 +511,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); | |||
509 | static int tiocmget(struct tty_struct *tty, struct file *file); | 511 | static int tiocmget(struct tty_struct *tty, struct file *file); |
510 | static int tiocmset(struct tty_struct *tty, struct file *file, | 512 | static int tiocmset(struct tty_struct *tty, struct file *file, |
511 | unsigned int set, unsigned int clear); | 513 | unsigned int set, unsigned int clear); |
512 | static void set_break(struct tty_struct *tty, int break_state); | 514 | static int set_break(struct tty_struct *tty, int break_state); |
513 | static int get_interface(struct slgt_info *info, int __user *if_mode); | 515 | static int get_interface(struct slgt_info *info, int __user *if_mode); |
514 | static int set_interface(struct slgt_info *info, int if_mode); | 516 | static int set_interface(struct slgt_info *info, int if_mode); |
515 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 517 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
@@ -845,6 +847,7 @@ static int write(struct tty_struct *tty, | |||
845 | int ret = 0; | 847 | int ret = 0; |
846 | struct slgt_info *info = tty->driver_data; | 848 | struct slgt_info *info = tty->driver_data; |
847 | unsigned long flags; | 849 | unsigned long flags; |
850 | unsigned int bufs_needed; | ||
848 | 851 | ||
849 | if (sanity_check(info, tty->name, "write")) | 852 | if (sanity_check(info, tty->name, "write")) |
850 | goto cleanup; | 853 | goto cleanup; |
@@ -861,25 +864,16 @@ static int write(struct tty_struct *tty, | |||
861 | if (!count) | 864 | if (!count) |
862 | goto cleanup; | 865 | goto cleanup; |
863 | 866 | ||
864 | if (info->params.mode == MGSL_MODE_RAW || | 867 | if (!info->tx_active && info->tx_count) { |
865 | info->params.mode == MGSL_MODE_MONOSYNC || | 868 | /* send accumulated data from send_char() */ |
866 | info->params.mode == MGSL_MODE_BISYNC) { | 869 | tx_load(info, info->tx_buf, info->tx_count); |
867 | unsigned int bufs_needed = (count/DMABUFSIZE); | 870 | goto start; |
868 | unsigned int bufs_free = free_tbuf_count(info); | ||
869 | if (count % DMABUFSIZE) | ||
870 | ++bufs_needed; | ||
871 | if (bufs_needed > bufs_free) | ||
872 | goto cleanup; | ||
873 | } else { | ||
874 | if (info->tx_active) | ||
875 | goto cleanup; | ||
876 | if (info->tx_count) { | ||
877 | /* send accumulated data from send_char() calls */ | ||
878 | /* as frame and wait before accepting more data. */ | ||
879 | tx_load(info, info->tx_buf, info->tx_count); | ||
880 | goto start; | ||
881 | } | ||
882 | } | 871 | } |
872 | bufs_needed = (count/DMABUFSIZE); | ||
873 | if (count % DMABUFSIZE) | ||
874 | ++bufs_needed; | ||
875 | if (bufs_needed > free_tbuf_count(info)) | ||
876 | goto cleanup; | ||
883 | 877 | ||
884 | ret = info->tx_count = count; | 878 | ret = info->tx_count = count; |
885 | tx_load(info, buf, count); | 879 | tx_load(info, buf, count); |
@@ -1392,10 +1386,12 @@ done: | |||
1392 | static int chars_in_buffer(struct tty_struct *tty) | 1386 | static int chars_in_buffer(struct tty_struct *tty) |
1393 | { | 1387 | { |
1394 | struct slgt_info *info = tty->driver_data; | 1388 | struct slgt_info *info = tty->driver_data; |
1389 | int count; | ||
1395 | if (sanity_check(info, tty->name, "chars_in_buffer")) | 1390 | if (sanity_check(info, tty->name, "chars_in_buffer")) |
1396 | return 0; | 1391 | return 0; |
1397 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); | 1392 | count = tbuf_bytes(info); |
1398 | return info->tx_count; | 1393 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); |
1394 | return count; | ||
1399 | } | 1395 | } |
1400 | 1396 | ||
1401 | /* | 1397 | /* |
@@ -1448,14 +1444,14 @@ static void unthrottle(struct tty_struct * tty) | |||
1448 | * set or clear transmit break condition | 1444 | * set or clear transmit break condition |
1449 | * break_state -1=set break condition, 0=clear | 1445 | * break_state -1=set break condition, 0=clear |
1450 | */ | 1446 | */ |
1451 | static void set_break(struct tty_struct *tty, int break_state) | 1447 | static int set_break(struct tty_struct *tty, int break_state) |
1452 | { | 1448 | { |
1453 | struct slgt_info *info = tty->driver_data; | 1449 | struct slgt_info *info = tty->driver_data; |
1454 | unsigned short value; | 1450 | unsigned short value; |
1455 | unsigned long flags; | 1451 | unsigned long flags; |
1456 | 1452 | ||
1457 | if (sanity_check(info, tty->name, "set_break")) | 1453 | if (sanity_check(info, tty->name, "set_break")) |
1458 | return; | 1454 | return -EINVAL; |
1459 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); | 1455 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); |
1460 | 1456 | ||
1461 | spin_lock_irqsave(&info->lock,flags); | 1457 | spin_lock_irqsave(&info->lock,flags); |
@@ -1466,6 +1462,7 @@ static void set_break(struct tty_struct *tty, int break_state) | |||
1466 | value &= ~BIT6; | 1462 | value &= ~BIT6; |
1467 | wr_reg16(info, TCR, value); | 1463 | wr_reg16(info, TCR, value); |
1468 | spin_unlock_irqrestore(&info->lock,flags); | 1464 | spin_unlock_irqrestore(&info->lock,flags); |
1465 | return 0; | ||
1469 | } | 1466 | } |
1470 | 1467 | ||
1471 | #if SYNCLINK_GENERIC_HDLC | 1468 | #if SYNCLINK_GENERIC_HDLC |
@@ -2675,8 +2672,31 @@ static int tx_abort(struct slgt_info *info) | |||
2675 | static int rx_enable(struct slgt_info *info, int enable) | 2672 | static int rx_enable(struct slgt_info *info, int enable) |
2676 | { | 2673 | { |
2677 | unsigned long flags; | 2674 | unsigned long flags; |
2678 | DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); | 2675 | unsigned int rbuf_fill_level; |
2676 | DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); | ||
2679 | spin_lock_irqsave(&info->lock,flags); | 2677 | spin_lock_irqsave(&info->lock,flags); |
2678 | /* | ||
2679 | * enable[31..16] = receive DMA buffer fill level | ||
2680 | * 0 = noop (leave fill level unchanged) | ||
2681 | * fill level must be multiple of 4 and <= buffer size | ||
2682 | */ | ||
2683 | rbuf_fill_level = ((unsigned int)enable) >> 16; | ||
2684 | if (rbuf_fill_level) { | ||
2685 | if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { | ||
2686 | spin_unlock_irqrestore(&info->lock, flags); | ||
2687 | return -EINVAL; | ||
2688 | } | ||
2689 | info->rbuf_fill_level = rbuf_fill_level; | ||
2690 | rx_stop(info); /* restart receiver to use new fill level */ | ||
2691 | } | ||
2692 | |||
2693 | /* | ||
2694 | * enable[1..0] = receiver enable command | ||
2695 | * 0 = disable | ||
2696 | * 1 = enable | ||
2697 | * 2 = enable or force hunt mode if already enabled | ||
2698 | */ | ||
2699 | enable &= 3; | ||
2680 | if (enable) { | 2700 | if (enable) { |
2681 | if (!info->rx_enabled) | 2701 | if (!info->rx_enabled) |
2682 | rx_start(info); | 2702 | rx_start(info); |
@@ -3442,7 +3462,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3442 | info->magic = MGSL_MAGIC; | 3462 | info->magic = MGSL_MAGIC; |
3443 | INIT_WORK(&info->task, bh_handler); | 3463 | INIT_WORK(&info->task, bh_handler); |
3444 | info->max_frame_size = 4096; | 3464 | info->max_frame_size = 4096; |
3445 | info->raw_rx_size = DMABUFSIZE; | 3465 | info->rbuf_fill_level = DMABUFSIZE; |
3446 | info->port.close_delay = 5*HZ/10; | 3466 | info->port.close_delay = 5*HZ/10; |
3447 | info->port.closing_wait = 30*HZ; | 3467 | info->port.closing_wait = 30*HZ; |
3448 | init_waitqueue_head(&info->status_event_wait_q); | 3468 | init_waitqueue_head(&info->status_event_wait_q); |
@@ -3929,15 +3949,7 @@ static void tdma_start(struct slgt_info *info) | |||
3929 | 3949 | ||
3930 | /* set 1st descriptor address */ | 3950 | /* set 1st descriptor address */ |
3931 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | 3951 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); |
3932 | switch(info->params.mode) { | 3952 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ |
3933 | case MGSL_MODE_RAW: | ||
3934 | case MGSL_MODE_MONOSYNC: | ||
3935 | case MGSL_MODE_BISYNC: | ||
3936 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3937 | break; | ||
3938 | default: | ||
3939 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3940 | } | ||
3941 | } | 3953 | } |
3942 | 3954 | ||
3943 | static void tx_stop(struct slgt_info *info) | 3955 | static void tx_stop(struct slgt_info *info) |
@@ -4140,7 +4152,7 @@ static void sync_mode(struct slgt_info *info) | |||
4140 | * 01 enable | 4152 | * 01 enable |
4141 | * 00 auto-CTS enable | 4153 | * 00 auto-CTS enable |
4142 | */ | 4154 | */ |
4143 | val = 0; | 4155 | val = BIT2; |
4144 | 4156 | ||
4145 | switch(info->params.mode) { | 4157 | switch(info->params.mode) { |
4146 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4158 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
@@ -4413,6 +4425,8 @@ static void msc_set_vcr(struct slgt_info *info) | |||
4413 | break; | 4425 | break; |
4414 | } | 4426 | } |
4415 | 4427 | ||
4428 | if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) | ||
4429 | val |= BIT4; | ||
4416 | if (info->signals & SerialSignal_DTR) | 4430 | if (info->signals & SerialSignal_DTR) |
4417 | val |= BIT3; | 4431 | val |= BIT3; |
4418 | if (info->signals & SerialSignal_RTS) | 4432 | if (info->signals & SerialSignal_RTS) |
@@ -4451,16 +4465,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last | |||
4451 | while(!done) { | 4465 | while(!done) { |
4452 | /* reset current buffer for reuse */ | 4466 | /* reset current buffer for reuse */ |
4453 | info->rbufs[i].status = 0; | 4467 | info->rbufs[i].status = 0; |
4454 | switch(info->params.mode) { | 4468 | set_desc_count(info->rbufs[i], info->rbuf_fill_level); |
4455 | case MGSL_MODE_RAW: | ||
4456 | case MGSL_MODE_MONOSYNC: | ||
4457 | case MGSL_MODE_BISYNC: | ||
4458 | set_desc_count(info->rbufs[i], info->raw_rx_size); | ||
4459 | break; | ||
4460 | default: | ||
4461 | set_desc_count(info->rbufs[i], DMABUFSIZE); | ||
4462 | } | ||
4463 | |||
4464 | if (i == last) | 4469 | if (i == last) |
4465 | done = 1; | 4470 | done = 1; |
4466 | if (++i == info->rbuf_count) | 4471 | if (++i == info->rbuf_count) |
@@ -4567,7 +4572,7 @@ check_again: | |||
4567 | 4572 | ||
4568 | DBGBH(("%s rx frame status=%04X size=%d\n", | 4573 | DBGBH(("%s rx frame status=%04X size=%d\n", |
4569 | info->device_name, status, framesize)); | 4574 | info->device_name, status, framesize)); |
4570 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | 4575 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); |
4571 | 4576 | ||
4572 | if (framesize) { | 4577 | if (framesize) { |
4573 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { | 4578 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { |
@@ -4587,7 +4592,7 @@ check_again: | |||
4587 | info->icount.rxok++; | 4592 | info->icount.rxok++; |
4588 | 4593 | ||
4589 | while(copy_count) { | 4594 | while(copy_count) { |
4590 | int partial_count = min(copy_count, DMABUFSIZE); | 4595 | int partial_count = min_t(int, copy_count, info->rbuf_fill_level); |
4591 | memcpy(p, info->rbufs[i].buf, partial_count); | 4596 | memcpy(p, info->rbufs[i].buf, partial_count); |
4592 | p += partial_count; | 4597 | p += partial_count; |
4593 | copy_count -= partial_count; | 4598 | copy_count -= partial_count; |
@@ -4679,6 +4684,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info) | |||
4679 | } | 4684 | } |
4680 | 4685 | ||
4681 | /* | 4686 | /* |
4687 | * return number of bytes in unsent transmit DMA buffers | ||
4688 | * and the serial controller tx FIFO | ||
4689 | */ | ||
4690 | static unsigned int tbuf_bytes(struct slgt_info *info) | ||
4691 | { | ||
4692 | unsigned int total_count = 0; | ||
4693 | unsigned int i = info->tbuf_current; | ||
4694 | unsigned int reg_value; | ||
4695 | unsigned int count; | ||
4696 | unsigned int active_buf_count = 0; | ||
4697 | |||
4698 | /* | ||
4699 | * Add descriptor counts for all tx DMA buffers. | ||
4700 | * If count is zero (cleared by DMA controller after read), | ||
4701 | * the buffer is complete or is actively being read from. | ||
4702 | * | ||
4703 | * Record buf_count of last buffer with zero count starting | ||
4704 | * from current ring position. buf_count is mirror | ||
4705 | * copy of count and is not cleared by serial controller. | ||
4706 | * If DMA controller is active, that buffer is actively | ||
4707 | * being read so add to total. | ||
4708 | */ | ||
4709 | do { | ||
4710 | count = desc_count(info->tbufs[i]); | ||
4711 | if (count) | ||
4712 | total_count += count; | ||
4713 | else if (!total_count) | ||
4714 | active_buf_count = info->tbufs[i].buf_count; | ||
4715 | if (++i == info->tbuf_count) | ||
4716 | i = 0; | ||
4717 | } while (i != info->tbuf_current); | ||
4718 | |||
4719 | /* read tx DMA status register */ | ||
4720 | reg_value = rd_reg32(info, TDCSR); | ||
4721 | |||
4722 | /* if tx DMA active, last zero count buffer is in use */ | ||
4723 | if (reg_value & BIT0) | ||
4724 | total_count += active_buf_count; | ||
4725 | |||
4726 | /* add tx FIFO count = reg_value[15..8] */ | ||
4727 | total_count += (reg_value >> 8) & 0xff; | ||
4728 | |||
4729 | /* if transmitter active add one byte for shift register */ | ||
4730 | if (info->tx_active) | ||
4731 | total_count++; | ||
4732 | |||
4733 | return total_count; | ||
4734 | } | ||
4735 | |||
4736 | /* | ||
4682 | * load transmit DMA buffer(s) with data | 4737 | * load transmit DMA buffer(s) with data |
4683 | */ | 4738 | */ |
4684 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4739 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
@@ -4716,6 +4771,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4716 | set_desc_eof(*d, 0); | 4771 | set_desc_eof(*d, 0); |
4717 | 4772 | ||
4718 | set_desc_count(*d, count); | 4773 | set_desc_count(*d, count); |
4774 | d->buf_count = count; | ||
4719 | } | 4775 | } |
4720 | 4776 | ||
4721 | info->tbuf_current = i; | 4777 | info->tbuf_current = i; |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index f2edfad360d3..6bdb44f7bec2 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -524,7 +524,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v | |||
524 | static int chars_in_buffer(struct tty_struct *tty); | 524 | static int chars_in_buffer(struct tty_struct *tty); |
525 | static void throttle(struct tty_struct * tty); | 525 | static void throttle(struct tty_struct * tty); |
526 | static void unthrottle(struct tty_struct * tty); | 526 | static void unthrottle(struct tty_struct * tty); |
527 | static void set_break(struct tty_struct *tty, int break_state); | 527 | static int set_break(struct tty_struct *tty, int break_state); |
528 | 528 | ||
529 | #if SYNCLINK_GENERIC_HDLC | 529 | #if SYNCLINK_GENERIC_HDLC |
530 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | 530 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) |
@@ -549,7 +549,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); | |||
549 | static int tiocmget(struct tty_struct *tty, struct file *file); | 549 | static int tiocmget(struct tty_struct *tty, struct file *file); |
550 | static int tiocmset(struct tty_struct *tty, struct file *file, | 550 | static int tiocmset(struct tty_struct *tty, struct file *file, |
551 | unsigned int set, unsigned int clear); | 551 | unsigned int set, unsigned int clear); |
552 | static void set_break(struct tty_struct *tty, int break_state); | 552 | static int set_break(struct tty_struct *tty, int break_state); |
553 | 553 | ||
554 | static void add_device(SLMP_INFO *info); | 554 | static void add_device(SLMP_INFO *info); |
555 | static void device_init(int adapter_num, struct pci_dev *pdev); | 555 | static void device_init(int adapter_num, struct pci_dev *pdev); |
@@ -1584,7 +1584,7 @@ static void unthrottle(struct tty_struct * tty) | |||
1584 | /* set or clear transmit break condition | 1584 | /* set or clear transmit break condition |
1585 | * break_state -1=set break condition, 0=clear | 1585 | * break_state -1=set break condition, 0=clear |
1586 | */ | 1586 | */ |
1587 | static void set_break(struct tty_struct *tty, int break_state) | 1587 | static int set_break(struct tty_struct *tty, int break_state) |
1588 | { | 1588 | { |
1589 | unsigned char RegValue; | 1589 | unsigned char RegValue; |
1590 | SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; | 1590 | SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; |
@@ -1595,7 +1595,7 @@ static void set_break(struct tty_struct *tty, int break_state) | |||
1595 | __FILE__,__LINE__, info->device_name, break_state); | 1595 | __FILE__,__LINE__, info->device_name, break_state); |
1596 | 1596 | ||
1597 | if (sanity_check(info, tty->name, "set_break")) | 1597 | if (sanity_check(info, tty->name, "set_break")) |
1598 | return; | 1598 | return -EINVAL; |
1599 | 1599 | ||
1600 | spin_lock_irqsave(&info->lock,flags); | 1600 | spin_lock_irqsave(&info->lock,flags); |
1601 | RegValue = read_reg(info, CTL); | 1601 | RegValue = read_reg(info, CTL); |
@@ -1605,6 +1605,7 @@ static void set_break(struct tty_struct *tty, int break_state) | |||
1605 | RegValue &= ~BIT3; | 1605 | RegValue &= ~BIT3; |
1606 | write_reg(info, CTL, RegValue); | 1606 | write_reg(info, CTL, RegValue); |
1607 | spin_unlock_irqrestore(&info->lock,flags); | 1607 | spin_unlock_irqrestore(&info->lock,flags); |
1608 | return 0; | ||
1608 | } | 1609 | } |
1609 | 1610 | ||
1610 | #if SYNCLINK_GENERIC_HDLC | 1611 | #if SYNCLINK_GENERIC_HDLC |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e1fc193d9396..ae766d868454 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) | |||
580 | } | 580 | } |
581 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | 581 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); |
582 | 582 | ||
583 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
584 | |||
583 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 585 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
584 | char *buf) | 586 | char *buf) |
585 | { | 587 | { |
586 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | 588 | u8 *data; |
587 | ssize_t rc; | 589 | ssize_t rc; |
588 | 590 | ||
589 | struct tpm_chip *chip = dev_get_drvdata(dev); | 591 | struct tpm_chip *chip = dev_get_drvdata(dev); |
590 | if (chip == NULL) | 592 | if (chip == NULL) |
591 | return -ENODEV; | 593 | return -ENODEV; |
592 | 594 | ||
595 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
596 | if (!data) | ||
597 | return -ENOMEM; | ||
598 | |||
593 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 599 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
594 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 600 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
595 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | 601 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; |
596 | 602 | ||
597 | rc = transmit_cmd(chip, data, sizeof(data), | 603 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
598 | "attemtping to determine the permanent state"); | 604 | "attemtping to determine the permanent enabled state"); |
599 | if (rc) | 605 | if (rc) { |
606 | kfree(data); | ||
600 | return 0; | 607 | return 0; |
601 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | 608 | } |
609 | |||
610 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
611 | |||
612 | kfree(data); | ||
613 | return rc; | ||
602 | } | 614 | } |
603 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | 615 | EXPORT_SYMBOL_GPL(tpm_show_enabled); |
604 | 616 | ||
605 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | 617 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, |
606 | char *buf) | 618 | char *buf) |
607 | { | 619 | { |
608 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | 620 | u8 *data; |
609 | ssize_t rc; | 621 | ssize_t rc; |
610 | 622 | ||
611 | struct tpm_chip *chip = dev_get_drvdata(dev); | 623 | struct tpm_chip *chip = dev_get_drvdata(dev); |
612 | if (chip == NULL) | 624 | if (chip == NULL) |
613 | return -ENODEV; | 625 | return -ENODEV; |
614 | 626 | ||
627 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
628 | if (!data) | ||
629 | return -ENOMEM; | ||
630 | |||
615 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 631 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
616 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 632 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
617 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | 633 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; |
618 | 634 | ||
619 | rc = transmit_cmd(chip, data, sizeof(data), | 635 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
620 | "attemtping to determine the permanent state"); | 636 | "attemtping to determine the permanent active state"); |
621 | if (rc) | 637 | if (rc) { |
638 | kfree(data); | ||
622 | return 0; | 639 | return 0; |
623 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | 640 | } |
641 | |||
642 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | ||
643 | |||
644 | kfree(data); | ||
645 | return rc; | ||
624 | } | 646 | } |
625 | EXPORT_SYMBOL_GPL(tpm_show_active); | 647 | EXPORT_SYMBOL_GPL(tpm_show_active); |
626 | 648 | ||
627 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | 649 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, |
628 | char *buf) | 650 | char *buf) |
629 | { | 651 | { |
630 | u8 data[sizeof(tpm_cap)]; | 652 | u8 *data; |
631 | ssize_t rc; | 653 | ssize_t rc; |
632 | 654 | ||
633 | struct tpm_chip *chip = dev_get_drvdata(dev); | 655 | struct tpm_chip *chip = dev_get_drvdata(dev); |
634 | if (chip == NULL) | 656 | if (chip == NULL) |
635 | return -ENODEV; | 657 | return -ENODEV; |
636 | 658 | ||
659 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
660 | if (!data) | ||
661 | return -ENOMEM; | ||
662 | |||
637 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 663 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
638 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 664 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
639 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | 665 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; |
640 | 666 | ||
641 | rc = transmit_cmd(chip, data, sizeof(data), | 667 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
642 | "attempting to determine the owner state"); | 668 | "attempting to determine the owner state"); |
643 | if (rc) | 669 | if (rc) { |
670 | kfree(data); | ||
644 | return 0; | 671 | return 0; |
645 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | 672 | } |
673 | |||
674 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
675 | |||
676 | kfree(data); | ||
677 | return rc; | ||
646 | } | 678 | } |
647 | EXPORT_SYMBOL_GPL(tpm_show_owned); | 679 | EXPORT_SYMBOL_GPL(tpm_show_owned); |
648 | 680 | ||
649 | ssize_t tpm_show_temp_deactivated(struct device * dev, | 681 | ssize_t tpm_show_temp_deactivated(struct device * dev, |
650 | struct device_attribute * attr, char *buf) | 682 | struct device_attribute * attr, char *buf) |
651 | { | 683 | { |
652 | u8 data[sizeof(tpm_cap)]; | 684 | u8 *data; |
653 | ssize_t rc; | 685 | ssize_t rc; |
654 | 686 | ||
655 | struct tpm_chip *chip = dev_get_drvdata(dev); | 687 | struct tpm_chip *chip = dev_get_drvdata(dev); |
656 | if (chip == NULL) | 688 | if (chip == NULL) |
657 | return -ENODEV; | 689 | return -ENODEV; |
658 | 690 | ||
691 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
692 | if (!data) | ||
693 | return -ENOMEM; | ||
694 | |||
659 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 695 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
660 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 696 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
661 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | 697 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; |
662 | 698 | ||
663 | rc = transmit_cmd(chip, data, sizeof(data), | 699 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
664 | "attempting to determine the temporary state"); | 700 | "attempting to determine the temporary state"); |
665 | if (rc) | 701 | if (rc) { |
702 | kfree(data); | ||
666 | return 0; | 703 | return 0; |
667 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | 704 | } |
705 | |||
706 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | ||
707 | |||
708 | kfree(data); | ||
709 | return rc; | ||
668 | } | 710 | } |
669 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | 711 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); |
670 | 712 | ||
@@ -678,7 +720,7 @@ static const u8 pcrread[] = { | |||
678 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 720 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
679 | char *buf) | 721 | char *buf) |
680 | { | 722 | { |
681 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; | 723 | u8 *data; |
682 | ssize_t rc; | 724 | ssize_t rc; |
683 | int i, j, num_pcrs; | 725 | int i, j, num_pcrs; |
684 | __be32 index; | 726 | __be32 index; |
@@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
688 | if (chip == NULL) | 730 | if (chip == NULL) |
689 | return -ENODEV; | 731 | return -ENODEV; |
690 | 732 | ||
733 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
734 | if (!data) | ||
735 | return -ENOMEM; | ||
736 | |||
691 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 737 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
692 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 738 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
693 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; | 739 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; |
694 | 740 | ||
695 | rc = transmit_cmd(chip, data, sizeof(data), | 741 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
696 | "attempting to determine the number of PCRS"); | 742 | "attempting to determine the number of PCRS"); |
697 | if (rc) | 743 | if (rc) { |
744 | kfree(data); | ||
698 | return 0; | 745 | return 0; |
746 | } | ||
699 | 747 | ||
700 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 748 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); |
701 | for (i = 0; i < num_pcrs; i++) { | 749 | for (i = 0; i < num_pcrs; i++) { |
702 | memcpy(data, pcrread, sizeof(pcrread)); | 750 | memcpy(data, pcrread, sizeof(pcrread)); |
703 | index = cpu_to_be32(i); | 751 | index = cpu_to_be32(i); |
704 | memcpy(data + 10, &index, 4); | 752 | memcpy(data + 10, &index, 4); |
705 | rc = transmit_cmd(chip, data, sizeof(data), | 753 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
706 | "attempting to read a PCR"); | 754 | "attempting to read a PCR"); |
707 | if (rc) | 755 | if (rc) |
708 | goto out; | 756 | goto out; |
@@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
712 | str += sprintf(str, "\n"); | 760 | str += sprintf(str, "\n"); |
713 | } | 761 | } |
714 | out: | 762 | out: |
763 | kfree(data); | ||
715 | return str - buf; | 764 | return str - buf; |
716 | } | 765 | } |
717 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | 766 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); |
@@ -795,7 +844,7 @@ static const u8 cap_version[] = { | |||
795 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 844 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
796 | char *buf) | 845 | char *buf) |
797 | { | 846 | { |
798 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | 847 | u8 *data; |
799 | ssize_t rc; | 848 | ssize_t rc; |
800 | char *str = buf; | 849 | char *str = buf; |
801 | 850 | ||
@@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | |||
803 | if (chip == NULL) | 852 | if (chip == NULL) |
804 | return -ENODEV; | 853 | return -ENODEV; |
805 | 854 | ||
855 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
856 | if (!data) | ||
857 | return -ENOMEM; | ||
858 | |||
806 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 859 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
807 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 860 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
808 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | 861 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; |
809 | 862 | ||
810 | rc = transmit_cmd(chip, data, sizeof(data), | 863 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
811 | "attempting to determine the manufacturer"); | 864 | "attempting to determine the manufacturer"); |
812 | if (rc) | 865 | if (rc) { |
866 | kfree(data); | ||
813 | return 0; | 867 | return 0; |
868 | } | ||
814 | 869 | ||
815 | str += sprintf(str, "Manufacturer: 0x%x\n", | 870 | str += sprintf(str, "Manufacturer: 0x%x\n", |
816 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 871 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); |
817 | 872 | ||
818 | memcpy(data, cap_version, sizeof(cap_version)); | 873 | memcpy(data, cap_version, sizeof(cap_version)); |
819 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | 874 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; |
820 | rc = transmit_cmd(chip, data, sizeof(data), | 875 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
821 | "attempting to determine the 1.1 version"); | 876 | "attempting to determine the 1.1 version"); |
822 | if (rc) | 877 | if (rc) |
823 | goto out; | 878 | goto out; |
@@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | |||
828 | (int) data[17]); | 883 | (int) data[17]); |
829 | 884 | ||
830 | out: | 885 | out: |
886 | kfree(data); | ||
831 | return str - buf; | 887 | return str - buf; |
832 | } | 888 | } |
833 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 889 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
@@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); | |||
835 | ssize_t tpm_show_caps_1_2(struct device * dev, | 891 | ssize_t tpm_show_caps_1_2(struct device * dev, |
836 | struct device_attribute * attr, char *buf) | 892 | struct device_attribute * attr, char *buf) |
837 | { | 893 | { |
838 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | 894 | u8 *data; |
839 | ssize_t len; | 895 | ssize_t len; |
840 | char *str = buf; | 896 | char *str = buf; |
841 | 897 | ||
@@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
843 | if (chip == NULL) | 899 | if (chip == NULL) |
844 | return -ENODEV; | 900 | return -ENODEV; |
845 | 901 | ||
902 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
903 | if (!data) | ||
904 | return -ENOMEM; | ||
905 | |||
846 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 906 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
847 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 907 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
848 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | 908 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; |
849 | 909 | ||
850 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | 910 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); |
851 | TPM_ERROR_SIZE) { | 911 | if (len <= TPM_ERROR_SIZE) { |
852 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 912 | dev_dbg(chip->dev, "A TPM error (%d) occurred " |
853 | "attempting to determine the manufacturer\n", | 913 | "attempting to determine the manufacturer\n", |
854 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | 914 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); |
915 | kfree(data); | ||
855 | return 0; | 916 | return 0; |
856 | } | 917 | } |
857 | 918 | ||
@@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
861 | memcpy(data, cap_version, sizeof(cap_version)); | 922 | memcpy(data, cap_version, sizeof(cap_version)); |
862 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | 923 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; |
863 | 924 | ||
864 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | 925 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); |
865 | TPM_ERROR_SIZE) { | 926 | if (len <= TPM_ERROR_SIZE) { |
866 | dev_err(chip->dev, "A TPM error (%d) occurred " | 927 | dev_err(chip->dev, "A TPM error (%d) occurred " |
867 | "attempting to determine the 1.2 version\n", | 928 | "attempting to determine the 1.2 version\n", |
868 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | 929 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); |
@@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
874 | (int) data[19]); | 935 | (int) data[19]); |
875 | 936 | ||
876 | out: | 937 | out: |
938 | kfree(data); | ||
877 | return str - buf; | 939 | return str - buf; |
878 | } | 940 | } |
879 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | 941 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); |
@@ -966,7 +1028,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
966 | size_t size, loff_t *off) | 1028 | size_t size, loff_t *off) |
967 | { | 1029 | { |
968 | struct tpm_chip *chip = file->private_data; | 1030 | struct tpm_chip *chip = file->private_data; |
969 | int in_size = size, out_size; | 1031 | size_t in_size = size, out_size; |
970 | 1032 | ||
971 | /* cannot perform a write until the read has cleared | 1033 | /* cannot perform a write until the read has cleared |
972 | either via tpm_read or a user_read_timer timeout */ | 1034 | either via tpm_read or a user_read_timer timeout */ |
@@ -1001,7 +1063,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
1001 | size_t size, loff_t *off) | 1063 | size_t size, loff_t *off) |
1002 | { | 1064 | { |
1003 | struct tpm_chip *chip = file->private_data; | 1065 | struct tpm_chip *chip = file->private_data; |
1004 | int ret_size; | 1066 | ssize_t ret_size; |
1005 | 1067 | ||
1006 | del_singleshot_timer_sync(&chip->user_read_timer); | 1068 | del_singleshot_timer_sync(&chip->user_read_timer); |
1007 | flush_scheduled_work(); | 1069 | flush_scheduled_work(); |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 60a2d2630e36..68f052b42ed7 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -448,7 +448,7 @@ out_free: | |||
448 | goto out; | 448 | goto out; |
449 | } | 449 | } |
450 | 450 | ||
451 | const struct file_operations tpm_ascii_bios_measurements_ops = { | 451 | static const struct file_operations tpm_ascii_bios_measurements_ops = { |
452 | .open = tpm_ascii_bios_measurements_open, | 452 | .open = tpm_ascii_bios_measurements_open, |
453 | .read = seq_read, | 453 | .read = seq_read, |
454 | .llseek = seq_lseek, | 454 | .llseek = seq_lseek, |
@@ -486,7 +486,7 @@ out_free: | |||
486 | goto out; | 486 | goto out; |
487 | } | 487 | } |
488 | 488 | ||
489 | const struct file_operations tpm_binary_bios_measurements_ops = { | 489 | static const struct file_operations tpm_binary_bios_measurements_ops = { |
490 | .open = tpm_binary_bios_measurements_open, | 490 | .open = tpm_binary_bios_measurements_open, |
491 | .read = seq_read, | 491 | .read = seq_read, |
492 | .llseek = seq_lseek, | 492 | .llseek = seq_lseek, |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7a977bc03e8..ed1879c0dd8d 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 = { | |||
622 | {"ATM1200", 0}, /* Atmel */ | 622 | {"ATM1200", 0}, /* Atmel */ |
623 | {"IFX0102", 0}, /* Infineon */ | 623 | {"IFX0102", 0}, /* Infineon */ |
624 | {"BCM0101", 0}, /* Broadcom */ | 624 | {"BCM0101", 0}, /* Broadcom */ |
625 | {"BCM0102", 0}, /* Broadcom */ | ||
625 | {"NSC1200", 0}, /* National */ | 626 | {"NSC1200", 0}, /* National */ |
626 | {"ICO0102", 0}, /* Intel */ | 627 | {"ICO0102", 0}, /* Intel */ |
627 | /* Add new here */ | 628 | /* Add new here */ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 82f6a8c86332..e1b46bc7e43c 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -656,558 +656,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | |||
656 | 656 | ||
657 | 657 | ||
658 | /** | 658 | /** |
659 | * tty_set_termios_ldisc - set ldisc field | ||
660 | * @tty: tty structure | ||
661 | * @num: line discipline number | ||
662 | * | ||
663 | * This is probably overkill for real world processors but | ||
664 | * they are not on hot paths so a little discipline won't do | ||
665 | * any harm. | ||
666 | * | ||
667 | * Locking: takes termios_mutex | ||
668 | */ | ||
669 | |||
670 | static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | ||
671 | { | ||
672 | mutex_lock(&tty->termios_mutex); | ||
673 | tty->termios->c_line = num; | ||
674 | mutex_unlock(&tty->termios_mutex); | ||
675 | } | ||
676 | |||
677 | /* | ||
678 | * This guards the refcounted line discipline lists. The lock | ||
679 | * must be taken with irqs off because there are hangup path | ||
680 | * callers who will do ldisc lookups and cannot sleep. | ||
681 | */ | ||
682 | |||
683 | static DEFINE_SPINLOCK(tty_ldisc_lock); | ||
684 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | ||
685 | /* Line disc dispatch table */ | ||
686 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; | ||
687 | |||
688 | /** | ||
689 | * tty_register_ldisc - install a line discipline | ||
690 | * @disc: ldisc number | ||
691 | * @new_ldisc: pointer to the ldisc object | ||
692 | * | ||
693 | * Installs a new line discipline into the kernel. The discipline | ||
694 | * is set up as unreferenced and then made available to the kernel | ||
695 | * from this point onwards. | ||
696 | * | ||
697 | * Locking: | ||
698 | * takes tty_ldisc_lock to guard against ldisc races | ||
699 | */ | ||
700 | |||
701 | int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) | ||
702 | { | ||
703 | unsigned long flags; | ||
704 | int ret = 0; | ||
705 | |||
706 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
707 | return -EINVAL; | ||
708 | |||
709 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
710 | tty_ldiscs[disc] = new_ldisc; | ||
711 | new_ldisc->num = disc; | ||
712 | new_ldisc->refcount = 0; | ||
713 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
714 | |||
715 | return ret; | ||
716 | } | ||
717 | EXPORT_SYMBOL(tty_register_ldisc); | ||
718 | |||
719 | /** | ||
720 | * tty_unregister_ldisc - unload a line discipline | ||
721 | * @disc: ldisc number | ||
722 | * @new_ldisc: pointer to the ldisc object | ||
723 | * | ||
724 | * Remove a line discipline from the kernel providing it is not | ||
725 | * currently in use. | ||
726 | * | ||
727 | * Locking: | ||
728 | * takes tty_ldisc_lock to guard against ldisc races | ||
729 | */ | ||
730 | |||
731 | int tty_unregister_ldisc(int disc) | ||
732 | { | ||
733 | unsigned long flags; | ||
734 | int ret = 0; | ||
735 | |||
736 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
737 | return -EINVAL; | ||
738 | |||
739 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
740 | if (tty_ldiscs[disc]->refcount) | ||
741 | ret = -EBUSY; | ||
742 | else | ||
743 | tty_ldiscs[disc] = NULL; | ||
744 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
745 | |||
746 | return ret; | ||
747 | } | ||
748 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
749 | |||
750 | |||
751 | /** | ||
752 | * tty_ldisc_try_get - try and reference an ldisc | ||
753 | * @disc: ldisc number | ||
754 | * @ld: tty ldisc structure to complete | ||
755 | * | ||
756 | * Attempt to open and lock a line discipline into place. Return | ||
757 | * the line discipline refcounted and assigned in ld. On an error | ||
758 | * report the error code back | ||
759 | */ | ||
760 | |||
761 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | ||
762 | { | ||
763 | unsigned long flags; | ||
764 | struct tty_ldisc_ops *ldops; | ||
765 | int err = -EINVAL; | ||
766 | |||
767 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
768 | ld->ops = NULL; | ||
769 | ldops = tty_ldiscs[disc]; | ||
770 | /* Check the entry is defined */ | ||
771 | if (ldops) { | ||
772 | /* If the module is being unloaded we can't use it */ | ||
773 | if (!try_module_get(ldops->owner)) | ||
774 | err = -EAGAIN; | ||
775 | else { | ||
776 | /* lock it */ | ||
777 | ldops->refcount++; | ||
778 | ld->ops = ldops; | ||
779 | err = 0; | ||
780 | } | ||
781 | } | ||
782 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
783 | return err; | ||
784 | } | ||
785 | |||
786 | /** | ||
787 | * tty_ldisc_get - take a reference to an ldisc | ||
788 | * @disc: ldisc number | ||
789 | * @ld: tty line discipline structure to use | ||
790 | * | ||
791 | * Takes a reference to a line discipline. Deals with refcounts and | ||
792 | * module locking counts. Returns NULL if the discipline is not available. | ||
793 | * Returns a pointer to the discipline and bumps the ref count if it is | ||
794 | * available | ||
795 | * | ||
796 | * Locking: | ||
797 | * takes tty_ldisc_lock to guard against ldisc races | ||
798 | */ | ||
799 | |||
800 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) | ||
801 | { | ||
802 | int err; | ||
803 | |||
804 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
805 | return -EINVAL; | ||
806 | err = tty_ldisc_try_get(disc, ld); | ||
807 | if (err == -EAGAIN) { | ||
808 | request_module("tty-ldisc-%d", disc); | ||
809 | err = tty_ldisc_try_get(disc, ld); | ||
810 | } | ||
811 | return err; | ||
812 | } | ||
813 | |||
814 | /** | ||
815 | * tty_ldisc_put - drop ldisc reference | ||
816 | * @disc: ldisc number | ||
817 | * | ||
818 | * Drop a reference to a line discipline. Manage refcounts and | ||
819 | * module usage counts | ||
820 | * | ||
821 | * Locking: | ||
822 | * takes tty_ldisc_lock to guard against ldisc races | ||
823 | */ | ||
824 | |||
825 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) | ||
826 | { | ||
827 | unsigned long flags; | ||
828 | int disc = ld->num; | ||
829 | |||
830 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | ||
831 | |||
832 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
833 | ld = tty_ldiscs[disc]; | ||
834 | BUG_ON(ld->refcount == 0); | ||
835 | ld->refcount--; | ||
836 | module_put(ld->owner); | ||
837 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
838 | } | ||
839 | |||
840 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | ||
841 | { | ||
842 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
843 | } | ||
844 | |||
845 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | ||
846 | { | ||
847 | (*pos)++; | ||
848 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
849 | } | ||
850 | |||
851 | static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | ||
852 | { | ||
853 | } | ||
854 | |||
855 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | ||
856 | { | ||
857 | int i = *(loff_t *)v; | ||
858 | struct tty_ldisc ld; | ||
859 | |||
860 | if (tty_ldisc_get(i, &ld) < 0) | ||
861 | return 0; | ||
862 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | ||
863 | tty_ldisc_put(ld.ops); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | static const struct seq_operations tty_ldiscs_seq_ops = { | ||
868 | .start = tty_ldiscs_seq_start, | ||
869 | .next = tty_ldiscs_seq_next, | ||
870 | .stop = tty_ldiscs_seq_stop, | ||
871 | .show = tty_ldiscs_seq_show, | ||
872 | }; | ||
873 | |||
874 | static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) | ||
875 | { | ||
876 | return seq_open(file, &tty_ldiscs_seq_ops); | ||
877 | } | ||
878 | |||
879 | const struct file_operations tty_ldiscs_proc_fops = { | ||
880 | .owner = THIS_MODULE, | ||
881 | .open = proc_tty_ldiscs_open, | ||
882 | .read = seq_read, | ||
883 | .llseek = seq_lseek, | ||
884 | .release = seq_release, | ||
885 | }; | ||
886 | |||
887 | /** | ||
888 | * tty_ldisc_assign - set ldisc on a tty | ||
889 | * @tty: tty to assign | ||
890 | * @ld: line discipline | ||
891 | * | ||
892 | * Install an instance of a line discipline into a tty structure. The | ||
893 | * ldisc must have a reference count above zero to ensure it remains/ | ||
894 | * The tty instance refcount starts at zero. | ||
895 | * | ||
896 | * Locking: | ||
897 | * Caller must hold references | ||
898 | */ | ||
899 | |||
900 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | ||
901 | { | ||
902 | ld->refcount = 0; | ||
903 | tty->ldisc = *ld; | ||
904 | } | ||
905 | |||
906 | /** | ||
907 | * tty_ldisc_try - internal helper | ||
908 | * @tty: the tty | ||
909 | * | ||
910 | * Make a single attempt to grab and bump the refcount on | ||
911 | * the tty ldisc. Return 0 on failure or 1 on success. This is | ||
912 | * used to implement both the waiting and non waiting versions | ||
913 | * of tty_ldisc_ref | ||
914 | * | ||
915 | * Locking: takes tty_ldisc_lock | ||
916 | */ | ||
917 | |||
918 | static int tty_ldisc_try(struct tty_struct *tty) | ||
919 | { | ||
920 | unsigned long flags; | ||
921 | struct tty_ldisc *ld; | ||
922 | int ret = 0; | ||
923 | |||
924 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
925 | ld = &tty->ldisc; | ||
926 | if (test_bit(TTY_LDISC, &tty->flags)) { | ||
927 | ld->refcount++; | ||
928 | ret = 1; | ||
929 | } | ||
930 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
931 | return ret; | ||
932 | } | ||
933 | |||
934 | /** | ||
935 | * tty_ldisc_ref_wait - wait for the tty ldisc | ||
936 | * @tty: tty device | ||
937 | * | ||
938 | * Dereference the line discipline for the terminal and take a | ||
939 | * reference to it. If the line discipline is in flux then | ||
940 | * wait patiently until it changes. | ||
941 | * | ||
942 | * Note: Must not be called from an IRQ/timer context. The caller | ||
943 | * must also be careful not to hold other locks that will deadlock | ||
944 | * against a discipline change, such as an existing ldisc reference | ||
945 | * (which we check for) | ||
946 | * | ||
947 | * Locking: call functions take tty_ldisc_lock | ||
948 | */ | ||
949 | |||
950 | struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | ||
951 | { | ||
952 | /* wait_event is a macro */ | ||
953 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | ||
954 | if (tty->ldisc.refcount == 0) | ||
955 | printk(KERN_ERR "tty_ldisc_ref_wait\n"); | ||
956 | return &tty->ldisc; | ||
957 | } | ||
958 | |||
959 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | ||
960 | |||
961 | /** | ||
962 | * tty_ldisc_ref - get the tty ldisc | ||
963 | * @tty: tty device | ||
964 | * | ||
965 | * Dereference the line discipline for the terminal and take a | ||
966 | * reference to it. If the line discipline is in flux then | ||
967 | * return NULL. Can be called from IRQ and timer functions. | ||
968 | * | ||
969 | * Locking: called functions take tty_ldisc_lock | ||
970 | */ | ||
971 | |||
972 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | ||
973 | { | ||
974 | if (tty_ldisc_try(tty)) | ||
975 | return &tty->ldisc; | ||
976 | return NULL; | ||
977 | } | ||
978 | |||
979 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | ||
980 | |||
981 | /** | ||
982 | * tty_ldisc_deref - free a tty ldisc reference | ||
983 | * @ld: reference to free up | ||
984 | * | ||
985 | * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May | ||
986 | * be called in IRQ context. | ||
987 | * | ||
988 | * Locking: takes tty_ldisc_lock | ||
989 | */ | ||
990 | |||
991 | void tty_ldisc_deref(struct tty_ldisc *ld) | ||
992 | { | ||
993 | unsigned long flags; | ||
994 | |||
995 | BUG_ON(ld == NULL); | ||
996 | |||
997 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
998 | if (ld->refcount == 0) | ||
999 | printk(KERN_ERR "tty_ldisc_deref: no references.\n"); | ||
1000 | else | ||
1001 | ld->refcount--; | ||
1002 | if (ld->refcount == 0) | ||
1003 | wake_up(&tty_ldisc_wait); | ||
1004 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
1005 | } | ||
1006 | |||
1007 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | ||
1008 | |||
1009 | /** | ||
1010 | * tty_ldisc_enable - allow ldisc use | ||
1011 | * @tty: terminal to activate ldisc on | ||
1012 | * | ||
1013 | * Set the TTY_LDISC flag when the line discipline can be called | ||
1014 | * again. Do necessary wakeups for existing sleepers. | ||
1015 | * | ||
1016 | * Note: nobody should set this bit except via this function. Clearing | ||
1017 | * directly is allowed. | ||
1018 | */ | ||
1019 | |||
1020 | static void tty_ldisc_enable(struct tty_struct *tty) | ||
1021 | { | ||
1022 | set_bit(TTY_LDISC, &tty->flags); | ||
1023 | wake_up(&tty_ldisc_wait); | ||
1024 | } | ||
1025 | |||
1026 | /** | ||
1027 | * tty_ldisc_restore - helper for tty ldisc change | ||
1028 | * @tty: tty to recover | ||
1029 | * @old: previous ldisc | ||
1030 | * | ||
1031 | * Restore the previous line discipline or N_TTY when a line discipline | ||
1032 | * change fails due to an open error | ||
1033 | */ | ||
1034 | |||
1035 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | ||
1036 | { | ||
1037 | char buf[64]; | ||
1038 | struct tty_ldisc new_ldisc; | ||
1039 | |||
1040 | /* There is an outstanding reference here so this is safe */ | ||
1041 | tty_ldisc_get(old->ops->num, old); | ||
1042 | tty_ldisc_assign(tty, old); | ||
1043 | tty_set_termios_ldisc(tty, old->ops->num); | ||
1044 | if (old->ops->open && (old->ops->open(tty) < 0)) { | ||
1045 | tty_ldisc_put(old->ops); | ||
1046 | /* This driver is always present */ | ||
1047 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | ||
1048 | panic("n_tty: get"); | ||
1049 | tty_ldisc_assign(tty, &new_ldisc); | ||
1050 | tty_set_termios_ldisc(tty, N_TTY); | ||
1051 | if (new_ldisc.ops->open) { | ||
1052 | int r = new_ldisc.ops->open(tty); | ||
1053 | if (r < 0) | ||
1054 | panic("Couldn't open N_TTY ldisc for " | ||
1055 | "%s --- error %d.", | ||
1056 | tty_name(tty, buf), r); | ||
1057 | } | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1061 | /** | ||
1062 | * tty_set_ldisc - set line discipline | ||
1063 | * @tty: the terminal to set | ||
1064 | * @ldisc: the line discipline | ||
1065 | * | ||
1066 | * Set the discipline of a tty line. Must be called from a process | ||
1067 | * context. | ||
1068 | * | ||
1069 | * Locking: takes tty_ldisc_lock. | ||
1070 | * called functions take termios_mutex | ||
1071 | */ | ||
1072 | |||
1073 | static int tty_set_ldisc(struct tty_struct *tty, int ldisc) | ||
1074 | { | ||
1075 | int retval; | ||
1076 | struct tty_ldisc o_ldisc, new_ldisc; | ||
1077 | int work; | ||
1078 | unsigned long flags; | ||
1079 | struct tty_struct *o_tty; | ||
1080 | |||
1081 | restart: | ||
1082 | /* This is a bit ugly for now but means we can break the 'ldisc | ||
1083 | is part of the tty struct' assumption later */ | ||
1084 | retval = tty_ldisc_get(ldisc, &new_ldisc); | ||
1085 | if (retval) | ||
1086 | return retval; | ||
1087 | |||
1088 | /* | ||
1089 | * Problem: What do we do if this blocks ? | ||
1090 | */ | ||
1091 | |||
1092 | tty_wait_until_sent(tty, 0); | ||
1093 | |||
1094 | if (tty->ldisc.ops->num == ldisc) { | ||
1095 | tty_ldisc_put(new_ldisc.ops); | ||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1099 | /* | ||
1100 | * No more input please, we are switching. The new ldisc | ||
1101 | * will update this value in the ldisc open function | ||
1102 | */ | ||
1103 | |||
1104 | tty->receive_room = 0; | ||
1105 | |||
1106 | o_ldisc = tty->ldisc; | ||
1107 | o_tty = tty->link; | ||
1108 | |||
1109 | /* | ||
1110 | * Make sure we don't change while someone holds a | ||
1111 | * reference to the line discipline. The TTY_LDISC bit | ||
1112 | * prevents anyone taking a reference once it is clear. | ||
1113 | * We need the lock to avoid racing reference takers. | ||
1114 | */ | ||
1115 | |||
1116 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
1117 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | ||
1118 | if (tty->ldisc.refcount) { | ||
1119 | /* Free the new ldisc we grabbed. Must drop the lock | ||
1120 | first. */ | ||
1121 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
1122 | tty_ldisc_put(o_ldisc.ops); | ||
1123 | /* | ||
1124 | * There are several reasons we may be busy, including | ||
1125 | * random momentary I/O traffic. We must therefore | ||
1126 | * retry. We could distinguish between blocking ops | ||
1127 | * and retries if we made tty_ldisc_wait() smarter. | ||
1128 | * That is up for discussion. | ||
1129 | */ | ||
1130 | if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) | ||
1131 | return -ERESTARTSYS; | ||
1132 | goto restart; | ||
1133 | } | ||
1134 | if (o_tty && o_tty->ldisc.refcount) { | ||
1135 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
1136 | tty_ldisc_put(o_tty->ldisc.ops); | ||
1137 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | ||
1138 | return -ERESTARTSYS; | ||
1139 | goto restart; | ||
1140 | } | ||
1141 | } | ||
1142 | /* | ||
1143 | * If the TTY_LDISC bit is set, then we are racing against | ||
1144 | * another ldisc change | ||
1145 | */ | ||
1146 | if (!test_bit(TTY_LDISC, &tty->flags)) { | ||
1147 | struct tty_ldisc *ld; | ||
1148 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
1149 | tty_ldisc_put(new_ldisc.ops); | ||
1150 | ld = tty_ldisc_ref_wait(tty); | ||
1151 | tty_ldisc_deref(ld); | ||
1152 | goto restart; | ||
1153 | } | ||
1154 | |||
1155 | clear_bit(TTY_LDISC, &tty->flags); | ||
1156 | if (o_tty) | ||
1157 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
1158 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
1159 | |||
1160 | /* | ||
1161 | * From this point on we know nobody has an ldisc | ||
1162 | * usage reference, nor can they obtain one until | ||
1163 | * we say so later on. | ||
1164 | */ | ||
1165 | |||
1166 | work = cancel_delayed_work(&tty->buf.work); | ||
1167 | /* | ||
1168 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
1169 | * MUST NOT hold locks here. | ||
1170 | */ | ||
1171 | flush_scheduled_work(); | ||
1172 | /* Shutdown the current discipline. */ | ||
1173 | if (o_ldisc.ops->close) | ||
1174 | (o_ldisc.ops->close)(tty); | ||
1175 | |||
1176 | /* Now set up the new line discipline. */ | ||
1177 | tty_ldisc_assign(tty, &new_ldisc); | ||
1178 | tty_set_termios_ldisc(tty, ldisc); | ||
1179 | if (new_ldisc.ops->open) | ||
1180 | retval = (new_ldisc.ops->open)(tty); | ||
1181 | if (retval < 0) { | ||
1182 | tty_ldisc_put(new_ldisc.ops); | ||
1183 | tty_ldisc_restore(tty, &o_ldisc); | ||
1184 | } | ||
1185 | /* At this point we hold a reference to the new ldisc and a | ||
1186 | a reference to the old ldisc. If we ended up flipping back | ||
1187 | to the existing ldisc we have two references to it */ | ||
1188 | |||
1189 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) | ||
1190 | tty->ops->set_ldisc(tty); | ||
1191 | |||
1192 | tty_ldisc_put(o_ldisc.ops); | ||
1193 | |||
1194 | /* | ||
1195 | * Allow ldisc referencing to occur as soon as the driver | ||
1196 | * ldisc callback completes. | ||
1197 | */ | ||
1198 | |||
1199 | tty_ldisc_enable(tty); | ||
1200 | if (o_tty) | ||
1201 | tty_ldisc_enable(o_tty); | ||
1202 | |||
1203 | /* Restart it in case no characters kick it off. Safe if | ||
1204 | already running */ | ||
1205 | if (work) | ||
1206 | schedule_delayed_work(&tty->buf.work, 1); | ||
1207 | return retval; | ||
1208 | } | ||
1209 | |||
1210 | /** | ||
1211 | * get_tty_driver - find device of a tty | 659 | * get_tty_driver - find device of a tty |
1212 | * @dev_t: device identifier | 660 | * @dev_t: device identifier |
1213 | * @index: returns the index of the tty | 661 | * @index: returns the index of the tty |
@@ -1467,7 +915,7 @@ static void tty_reset_termios(struct tty_struct *tty) | |||
1467 | * do_tty_hangup - actual handler for hangup events | 915 | * do_tty_hangup - actual handler for hangup events |
1468 | * @work: tty device | 916 | * @work: tty device |
1469 | * | 917 | * |
1470 | k * This can be called by the "eventd" kernel thread. That is process | 918 | * This can be called by the "eventd" kernel thread. That is process |
1471 | * synchronous but doesn't hold any locks, so we need to make sure we | 919 | * synchronous but doesn't hold any locks, so we need to make sure we |
1472 | * have the appropriate locks for what we're doing. | 920 | * have the appropriate locks for what we're doing. |
1473 | * | 921 | * |
@@ -1671,19 +1119,6 @@ int tty_hung_up_p(struct file *filp) | |||
1671 | 1119 | ||
1672 | EXPORT_SYMBOL(tty_hung_up_p); | 1120 | EXPORT_SYMBOL(tty_hung_up_p); |
1673 | 1121 | ||
1674 | /** | ||
1675 | * is_tty - checker whether file is a TTY | ||
1676 | * @filp: file handle that may be a tty | ||
1677 | * | ||
1678 | * Check if the file handle is a tty handle. | ||
1679 | */ | ||
1680 | |||
1681 | int is_tty(struct file *filp) | ||
1682 | { | ||
1683 | return filp->f_op->read == tty_read | ||
1684 | || filp->f_op->read == hung_up_tty_read; | ||
1685 | } | ||
1686 | |||
1687 | static void session_clear_tty(struct pid *session) | 1122 | static void session_clear_tty(struct pid *session) |
1688 | { | 1123 | { |
1689 | struct task_struct *p; | 1124 | struct task_struct *p; |
@@ -2193,7 +1628,6 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2193 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; | 1628 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; |
2194 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; | 1629 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; |
2195 | int retval = 0; | 1630 | int retval = 0; |
2196 | struct tty_ldisc *ld; | ||
2197 | 1631 | ||
2198 | /* check whether we're reopening an existing tty */ | 1632 | /* check whether we're reopening an existing tty */ |
2199 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | 1633 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { |
@@ -2342,25 +1776,12 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2342 | * If we fail here just call release_tty to clean up. No need | 1776 | * If we fail here just call release_tty to clean up. No need |
2343 | * to decrement the use counts, as release_tty doesn't care. | 1777 | * to decrement the use counts, as release_tty doesn't care. |
2344 | */ | 1778 | */ |
2345 | |||
2346 | ld = &tty->ldisc; | ||
2347 | 1779 | ||
2348 | if (ld->ops->open) { | 1780 | retval = tty_ldisc_setup(tty, o_tty); |
2349 | retval = (ld->ops->open)(tty); | 1781 | |
2350 | if (retval) | 1782 | if (retval) |
2351 | goto release_mem_out; | 1783 | goto release_mem_out; |
2352 | } | 1784 | goto success; |
2353 | if (o_tty && o_tty->ldisc.ops->open) { | ||
2354 | retval = (o_tty->ldisc.ops->open)(o_tty); | ||
2355 | if (retval) { | ||
2356 | if (ld->ops->close) | ||
2357 | (ld->ops->close)(tty); | ||
2358 | goto release_mem_out; | ||
2359 | } | ||
2360 | tty_ldisc_enable(o_tty); | ||
2361 | } | ||
2362 | tty_ldisc_enable(tty); | ||
2363 | goto success; | ||
2364 | 1785 | ||
2365 | /* | 1786 | /* |
2366 | * This fast open can be used if the tty is already open. | 1787 | * This fast open can be used if the tty is already open. |
@@ -2498,12 +1919,10 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
2498 | static void release_dev(struct file *filp) | 1919 | static void release_dev(struct file *filp) |
2499 | { | 1920 | { |
2500 | struct tty_struct *tty, *o_tty; | 1921 | struct tty_struct *tty, *o_tty; |
2501 | struct tty_ldisc ld; | ||
2502 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1922 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
2503 | int devpts; | 1923 | int devpts; |
2504 | int idx; | 1924 | int idx; |
2505 | char buf[64]; | 1925 | char buf[64]; |
2506 | unsigned long flags; | ||
2507 | 1926 | ||
2508 | tty = (struct tty_struct *)filp->private_data; | 1927 | tty = (struct tty_struct *)filp->private_data; |
2509 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, | 1928 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, |
@@ -2705,56 +2124,9 @@ static void release_dev(struct file *filp) | |||
2705 | printk(KERN_DEBUG "freeing tty structure..."); | 2124 | printk(KERN_DEBUG "freeing tty structure..."); |
2706 | #endif | 2125 | #endif |
2707 | /* | 2126 | /* |
2708 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then | 2127 | * Ask the line discipline code to release its structures |
2709 | * kill any delayed work. As this is the final close it does not | ||
2710 | * race with the set_ldisc code path. | ||
2711 | */ | 2128 | */ |
2712 | clear_bit(TTY_LDISC, &tty->flags); | 2129 | tty_ldisc_release(tty, o_tty); |
2713 | cancel_delayed_work(&tty->buf.work); | ||
2714 | |||
2715 | /* | ||
2716 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
2717 | */ | ||
2718 | |||
2719 | flush_scheduled_work(); | ||
2720 | |||
2721 | /* | ||
2722 | * Wait for any short term users (we know they are just driver | ||
2723 | * side waiters as the file is closing so user count on the file | ||
2724 | * side is zero. | ||
2725 | */ | ||
2726 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
2727 | while (tty->ldisc.refcount) { | ||
2728 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
2729 | wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); | ||
2730 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
2731 | } | ||
2732 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
2733 | /* | ||
2734 | * Shutdown the current line discipline, and reset it to N_TTY. | ||
2735 | * | ||
2736 | * FIXME: this MUST get fixed for the new reflocking | ||
2737 | */ | ||
2738 | if (tty->ldisc.ops->close) | ||
2739 | (tty->ldisc.ops->close)(tty); | ||
2740 | tty_ldisc_put(tty->ldisc.ops); | ||
2741 | |||
2742 | /* | ||
2743 | * Switch the line discipline back | ||
2744 | */ | ||
2745 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
2746 | tty_ldisc_assign(tty, &ld); | ||
2747 | tty_set_termios_ldisc(tty, N_TTY); | ||
2748 | if (o_tty) { | ||
2749 | /* FIXME: could o_tty be in setldisc here ? */ | ||
2750 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
2751 | if (o_tty->ldisc.ops->close) | ||
2752 | (o_tty->ldisc.ops->close)(o_tty); | ||
2753 | tty_ldisc_put(o_tty->ldisc.ops); | ||
2754 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
2755 | tty_ldisc_assign(o_tty, &ld); | ||
2756 | tty_set_termios_ldisc(o_tty, N_TTY); | ||
2757 | } | ||
2758 | /* | 2130 | /* |
2759 | * The release_tty function takes care of the details of clearing | 2131 | * The release_tty function takes care of the details of clearing |
2760 | * the slots and preserving the termios structure. | 2132 | * the slots and preserving the termios structure. |
@@ -3464,16 +2836,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
3464 | 2836 | ||
3465 | static int send_break(struct tty_struct *tty, unsigned int duration) | 2837 | static int send_break(struct tty_struct *tty, unsigned int duration) |
3466 | { | 2838 | { |
3467 | if (tty_write_lock(tty, 0) < 0) | 2839 | int retval; |
3468 | return -EINTR; | 2840 | |
3469 | tty->ops->break_ctl(tty, -1); | 2841 | if (tty->ops->break_ctl == NULL) |
3470 | if (!signal_pending(current)) | 2842 | return 0; |
3471 | msleep_interruptible(duration); | 2843 | |
3472 | tty->ops->break_ctl(tty, 0); | 2844 | if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK) |
3473 | tty_write_unlock(tty); | 2845 | retval = tty->ops->break_ctl(tty, duration); |
3474 | if (signal_pending(current)) | 2846 | else { |
3475 | return -EINTR; | 2847 | /* Do the work ourselves */ |
3476 | return 0; | 2848 | if (tty_write_lock(tty, 0) < 0) |
2849 | return -EINTR; | ||
2850 | retval = tty->ops->break_ctl(tty, -1); | ||
2851 | if (retval) | ||
2852 | goto out; | ||
2853 | if (!signal_pending(current)) | ||
2854 | msleep_interruptible(duration); | ||
2855 | retval = tty->ops->break_ctl(tty, 0); | ||
2856 | out: | ||
2857 | tty_write_unlock(tty); | ||
2858 | if (signal_pending(current)) | ||
2859 | retval = -EINTR; | ||
2860 | } | ||
2861 | return retval; | ||
3477 | } | 2862 | } |
3478 | 2863 | ||
3479 | /** | 2864 | /** |
@@ -3564,36 +2949,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3564 | tty->driver->subtype == PTY_TYPE_MASTER) | 2949 | tty->driver->subtype == PTY_TYPE_MASTER) |
3565 | real_tty = tty->link; | 2950 | real_tty = tty->link; |
3566 | 2951 | ||
3567 | /* | ||
3568 | * Break handling by driver | ||
3569 | */ | ||
3570 | |||
3571 | retval = -EINVAL; | ||
3572 | |||
3573 | if (!tty->ops->break_ctl) { | ||
3574 | switch (cmd) { | ||
3575 | case TIOCSBRK: | ||
3576 | case TIOCCBRK: | ||
3577 | if (tty->ops->ioctl) | ||
3578 | retval = tty->ops->ioctl(tty, file, cmd, arg); | ||
3579 | if (retval != -EINVAL && retval != -ENOIOCTLCMD) | ||
3580 | printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); | ||
3581 | return retval; | ||
3582 | |||
3583 | /* These two ioctl's always return success; even if */ | ||
3584 | /* the driver doesn't support them. */ | ||
3585 | case TCSBRK: | ||
3586 | case TCSBRKP: | ||
3587 | if (!tty->ops->ioctl) | ||
3588 | return 0; | ||
3589 | retval = tty->ops->ioctl(tty, file, cmd, arg); | ||
3590 | if (retval != -EINVAL && retval != -ENOIOCTLCMD) | ||
3591 | printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); | ||
3592 | if (retval == -ENOIOCTLCMD) | ||
3593 | retval = 0; | ||
3594 | return retval; | ||
3595 | } | ||
3596 | } | ||
3597 | 2952 | ||
3598 | /* | 2953 | /* |
3599 | * Factor out some common prep work | 2954 | * Factor out some common prep work |
@@ -3615,6 +2970,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3615 | break; | 2970 | break; |
3616 | } | 2971 | } |
3617 | 2972 | ||
2973 | /* | ||
2974 | * Now do the stuff. | ||
2975 | */ | ||
3618 | switch (cmd) { | 2976 | switch (cmd) { |
3619 | case TIOCSTI: | 2977 | case TIOCSTI: |
3620 | return tiocsti(tty, p); | 2978 | return tiocsti(tty, p); |
@@ -3658,12 +3016,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3658 | */ | 3016 | */ |
3659 | case TIOCSBRK: /* Turn break on, unconditionally */ | 3017 | case TIOCSBRK: /* Turn break on, unconditionally */ |
3660 | if (tty->ops->break_ctl) | 3018 | if (tty->ops->break_ctl) |
3661 | tty->ops->break_ctl(tty, -1); | 3019 | return tty->ops->break_ctl(tty, -1); |
3662 | return 0; | 3020 | return 0; |
3663 | |||
3664 | case TIOCCBRK: /* Turn break off, unconditionally */ | 3021 | case TIOCCBRK: /* Turn break off, unconditionally */ |
3665 | if (tty->ops->break_ctl) | 3022 | if (tty->ops->break_ctl) |
3666 | tty->ops->break_ctl(tty, 0); | 3023 | return tty->ops->break_ctl(tty, 0); |
3667 | return 0; | 3024 | return 0; |
3668 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 3025 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
3669 | /* non-zero arg means wait for all output data | 3026 | /* non-zero arg means wait for all output data |
@@ -3962,12 +3319,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push); | |||
3962 | 3319 | ||
3963 | static void initialize_tty_struct(struct tty_struct *tty) | 3320 | static void initialize_tty_struct(struct tty_struct *tty) |
3964 | { | 3321 | { |
3965 | struct tty_ldisc ld; | ||
3966 | memset(tty, 0, sizeof(struct tty_struct)); | 3322 | memset(tty, 0, sizeof(struct tty_struct)); |
3967 | tty->magic = TTY_MAGIC; | 3323 | tty->magic = TTY_MAGIC; |
3968 | if (tty_ldisc_get(N_TTY, &ld) < 0) | 3324 | tty_ldisc_init(tty); |
3969 | panic("n_tty: init_tty"); | ||
3970 | tty_ldisc_assign(tty, &ld); | ||
3971 | tty->session = NULL; | 3325 | tty->session = NULL; |
3972 | tty->pgrp = NULL; | 3326 | tty->pgrp = NULL; |
3973 | tty->overrun_time = jiffies; | 3327 | tty->overrun_time = jiffies; |
@@ -4045,7 +3399,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, | |||
4045 | else | 3399 | else |
4046 | tty_line_name(driver, index, name); | 3400 | tty_line_name(driver, index, name); |
4047 | 3401 | ||
4048 | return device_create(tty_class, device, dev, name); | 3402 | return device_create_drvdata(tty_class, device, dev, NULL, name); |
4049 | } | 3403 | } |
4050 | 3404 | ||
4051 | /** | 3405 | /** |
@@ -4226,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p) | |||
4226 | p->signal->tty = NULL; | 3580 | p->signal->tty = NULL; |
4227 | spin_unlock_irq(&p->sighand->siglock); | 3581 | spin_unlock_irq(&p->sighand->siglock); |
4228 | } | 3582 | } |
4229 | EXPORT_SYMBOL(proc_clear_tty); | ||
4230 | 3583 | ||
4231 | /* Called under the sighand lock */ | 3584 | /* Called under the sighand lock */ |
4232 | 3585 | ||
@@ -4280,7 +3633,7 @@ void __init console_init(void) | |||
4280 | initcall_t *call; | 3633 | initcall_t *call; |
4281 | 3634 | ||
4282 | /* Setup the default TTY line discipline. */ | 3635 | /* Setup the default TTY line discipline. */ |
4283 | (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); | 3636 | tty_ldisc_begin(); |
4284 | 3637 | ||
4285 | /* | 3638 | /* |
4286 | * set up the console device so that later boot sequences can | 3639 | * set up the console device so that later boot sequences can |
@@ -4323,20 +3676,22 @@ static int __init tty_init(void) | |||
4323 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || | 3676 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
4324 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) | 3677 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
4325 | panic("Couldn't register /dev/tty driver\n"); | 3678 | panic("Couldn't register /dev/tty driver\n"); |
4326 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty"); | 3679 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, |
3680 | "tty"); | ||
4327 | 3681 | ||
4328 | cdev_init(&console_cdev, &console_fops); | 3682 | cdev_init(&console_cdev, &console_fops); |
4329 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || | 3683 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || |
4330 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) | 3684 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) |
4331 | panic("Couldn't register /dev/console driver\n"); | 3685 | panic("Couldn't register /dev/console driver\n"); |
4332 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console"); | 3686 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, |
3687 | "console"); | ||
4333 | 3688 | ||
4334 | #ifdef CONFIG_UNIX98_PTYS | 3689 | #ifdef CONFIG_UNIX98_PTYS |
4335 | cdev_init(&ptmx_cdev, &ptmx_fops); | 3690 | cdev_init(&ptmx_cdev, &ptmx_fops); |
4336 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || | 3691 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || |
4337 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) | 3692 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) |
4338 | panic("Couldn't register /dev/ptmx driver\n"); | 3693 | panic("Couldn't register /dev/ptmx driver\n"); |
4339 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx"); | 3694 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); |
4340 | #endif | 3695 | #endif |
4341 | 3696 | ||
4342 | #ifdef CONFIG_VT | 3697 | #ifdef CONFIG_VT |
@@ -4344,7 +3699,7 @@ static int __init tty_init(void) | |||
4344 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || | 3699 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || |
4345 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) | 3700 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) |
4346 | panic("Couldn't register /dev/tty0 driver\n"); | 3701 | panic("Couldn't register /dev/tty0 driver\n"); |
4347 | device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0"); | 3702 | device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); |
4348 | 3703 | ||
4349 | vty_init(); | 3704 | vty_init(); |
4350 | #endif | 3705 | #endif |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c new file mode 100644 index 000000000000..f307f135cbfb --- /dev/null +++ b/drivers/char/tty_ldisc.c | |||
@@ -0,0 +1,714 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/major.h> | ||
3 | #include <linux/errno.h> | ||
4 | #include <linux/signal.h> | ||
5 | #include <linux/fcntl.h> | ||
6 | #include <linux/sched.h> | ||
7 | #include <linux/interrupt.h> | ||
8 | #include <linux/tty.h> | ||
9 | #include <linux/tty_driver.h> | ||
10 | #include <linux/tty_flip.h> | ||
11 | #include <linux/devpts_fs.h> | ||
12 | #include <linux/file.h> | ||
13 | #include <linux/fdtable.h> | ||
14 | #include <linux/console.h> | ||
15 | #include <linux/timer.h> | ||
16 | #include <linux/ctype.h> | ||
17 | #include <linux/kd.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/poll.h> | ||
22 | #include <linux/proc_fs.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/smp_lock.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/wait.h> | ||
28 | #include <linux/bitops.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/seq_file.h> | ||
31 | |||
32 | #include <linux/uaccess.h> | ||
33 | #include <asm/system.h> | ||
34 | |||
35 | #include <linux/kbd_kern.h> | ||
36 | #include <linux/vt_kern.h> | ||
37 | #include <linux/selection.h> | ||
38 | |||
39 | #include <linux/kmod.h> | ||
40 | #include <linux/nsproxy.h> | ||
41 | |||
42 | /* | ||
43 | * This guards the refcounted line discipline lists. The lock | ||
44 | * must be taken with irqs off because there are hangup path | ||
45 | * callers who will do ldisc lookups and cannot sleep. | ||
46 | */ | ||
47 | |||
48 | static DEFINE_SPINLOCK(tty_ldisc_lock); | ||
49 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | ||
50 | /* Line disc dispatch table */ | ||
51 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; | ||
52 | |||
53 | /** | ||
54 | * tty_register_ldisc - install a line discipline | ||
55 | * @disc: ldisc number | ||
56 | * @new_ldisc: pointer to the ldisc object | ||
57 | * | ||
58 | * Installs a new line discipline into the kernel. The discipline | ||
59 | * is set up as unreferenced and then made available to the kernel | ||
60 | * from this point onwards. | ||
61 | * | ||
62 | * Locking: | ||
63 | * takes tty_ldisc_lock to guard against ldisc races | ||
64 | */ | ||
65 | |||
66 | int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | int ret = 0; | ||
70 | |||
71 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
72 | return -EINVAL; | ||
73 | |||
74 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
75 | tty_ldiscs[disc] = new_ldisc; | ||
76 | new_ldisc->num = disc; | ||
77 | new_ldisc->refcount = 0; | ||
78 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | EXPORT_SYMBOL(tty_register_ldisc); | ||
83 | |||
84 | /** | ||
85 | * tty_unregister_ldisc - unload a line discipline | ||
86 | * @disc: ldisc number | ||
87 | * @new_ldisc: pointer to the ldisc object | ||
88 | * | ||
89 | * Remove a line discipline from the kernel providing it is not | ||
90 | * currently in use. | ||
91 | * | ||
92 | * Locking: | ||
93 | * takes tty_ldisc_lock to guard against ldisc races | ||
94 | */ | ||
95 | |||
96 | int tty_unregister_ldisc(int disc) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | int ret = 0; | ||
100 | |||
101 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
102 | return -EINVAL; | ||
103 | |||
104 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
105 | if (tty_ldiscs[disc]->refcount) | ||
106 | ret = -EBUSY; | ||
107 | else | ||
108 | tty_ldiscs[disc] = NULL; | ||
109 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
114 | |||
115 | |||
116 | /** | ||
117 | * tty_ldisc_try_get - try and reference an ldisc | ||
118 | * @disc: ldisc number | ||
119 | * @ld: tty ldisc structure to complete | ||
120 | * | ||
121 | * Attempt to open and lock a line discipline into place. Return | ||
122 | * the line discipline refcounted and assigned in ld. On an error | ||
123 | * report the error code back | ||
124 | */ | ||
125 | |||
126 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | struct tty_ldisc_ops *ldops; | ||
130 | int err = -EINVAL; | ||
131 | |||
132 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
133 | ld->ops = NULL; | ||
134 | ldops = tty_ldiscs[disc]; | ||
135 | /* Check the entry is defined */ | ||
136 | if (ldops) { | ||
137 | /* If the module is being unloaded we can't use it */ | ||
138 | if (!try_module_get(ldops->owner)) | ||
139 | err = -EAGAIN; | ||
140 | else { | ||
141 | /* lock it */ | ||
142 | ldops->refcount++; | ||
143 | ld->ops = ldops; | ||
144 | err = 0; | ||
145 | } | ||
146 | } | ||
147 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * tty_ldisc_get - take a reference to an ldisc | ||
153 | * @disc: ldisc number | ||
154 | * @ld: tty line discipline structure to use | ||
155 | * | ||
156 | * Takes a reference to a line discipline. Deals with refcounts and | ||
157 | * module locking counts. Returns NULL if the discipline is not available. | ||
158 | * Returns a pointer to the discipline and bumps the ref count if it is | ||
159 | * available | ||
160 | * | ||
161 | * Locking: | ||
162 | * takes tty_ldisc_lock to guard against ldisc races | ||
163 | */ | ||
164 | |||
165 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) | ||
166 | { | ||
167 | int err; | ||
168 | |||
169 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
170 | return -EINVAL; | ||
171 | err = tty_ldisc_try_get(disc, ld); | ||
172 | if (err < 0) { | ||
173 | request_module("tty-ldisc-%d", disc); | ||
174 | err = tty_ldisc_try_get(disc, ld); | ||
175 | } | ||
176 | return err; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * tty_ldisc_put - drop ldisc reference | ||
181 | * @disc: ldisc number | ||
182 | * | ||
183 | * Drop a reference to a line discipline. Manage refcounts and | ||
184 | * module usage counts | ||
185 | * | ||
186 | * Locking: | ||
187 | * takes tty_ldisc_lock to guard against ldisc races | ||
188 | */ | ||
189 | |||
190 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) | ||
191 | { | ||
192 | unsigned long flags; | ||
193 | int disc = ld->num; | ||
194 | |||
195 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | ||
196 | |||
197 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
198 | ld = tty_ldiscs[disc]; | ||
199 | BUG_ON(ld->refcount == 0); | ||
200 | ld->refcount--; | ||
201 | module_put(ld->owner); | ||
202 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
203 | } | ||
204 | |||
205 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | ||
206 | { | ||
207 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
208 | } | ||
209 | |||
210 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | ||
211 | { | ||
212 | (*pos)++; | ||
213 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
214 | } | ||
215 | |||
216 | static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | ||
217 | { | ||
218 | } | ||
219 | |||
220 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | ||
221 | { | ||
222 | int i = *(loff_t *)v; | ||
223 | struct tty_ldisc ld; | ||
224 | |||
225 | if (tty_ldisc_get(i, &ld) < 0) | ||
226 | return 0; | ||
227 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | ||
228 | tty_ldisc_put(ld.ops); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static const struct seq_operations tty_ldiscs_seq_ops = { | ||
233 | .start = tty_ldiscs_seq_start, | ||
234 | .next = tty_ldiscs_seq_next, | ||
235 | .stop = tty_ldiscs_seq_stop, | ||
236 | .show = tty_ldiscs_seq_show, | ||
237 | }; | ||
238 | |||
239 | static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) | ||
240 | { | ||
241 | return seq_open(file, &tty_ldiscs_seq_ops); | ||
242 | } | ||
243 | |||
244 | const struct file_operations tty_ldiscs_proc_fops = { | ||
245 | .owner = THIS_MODULE, | ||
246 | .open = proc_tty_ldiscs_open, | ||
247 | .read = seq_read, | ||
248 | .llseek = seq_lseek, | ||
249 | .release = seq_release, | ||
250 | }; | ||
251 | |||
252 | /** | ||
253 | * tty_ldisc_assign - set ldisc on a tty | ||
254 | * @tty: tty to assign | ||
255 | * @ld: line discipline | ||
256 | * | ||
257 | * Install an instance of a line discipline into a tty structure. The | ||
258 | * ldisc must have a reference count above zero to ensure it remains/ | ||
259 | * The tty instance refcount starts at zero. | ||
260 | * | ||
261 | * Locking: | ||
262 | * Caller must hold references | ||
263 | */ | ||
264 | |||
265 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | ||
266 | { | ||
267 | ld->refcount = 0; | ||
268 | tty->ldisc = *ld; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * tty_ldisc_try - internal helper | ||
273 | * @tty: the tty | ||
274 | * | ||
275 | * Make a single attempt to grab and bump the refcount on | ||
276 | * the tty ldisc. Return 0 on failure or 1 on success. This is | ||
277 | * used to implement both the waiting and non waiting versions | ||
278 | * of tty_ldisc_ref | ||
279 | * | ||
280 | * Locking: takes tty_ldisc_lock | ||
281 | */ | ||
282 | |||
283 | static int tty_ldisc_try(struct tty_struct *tty) | ||
284 | { | ||
285 | unsigned long flags; | ||
286 | struct tty_ldisc *ld; | ||
287 | int ret = 0; | ||
288 | |||
289 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
290 | ld = &tty->ldisc; | ||
291 | if (test_bit(TTY_LDISC, &tty->flags)) { | ||
292 | ld->refcount++; | ||
293 | ret = 1; | ||
294 | } | ||
295 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * tty_ldisc_ref_wait - wait for the tty ldisc | ||
301 | * @tty: tty device | ||
302 | * | ||
303 | * Dereference the line discipline for the terminal and take a | ||
304 | * reference to it. If the line discipline is in flux then | ||
305 | * wait patiently until it changes. | ||
306 | * | ||
307 | * Note: Must not be called from an IRQ/timer context. The caller | ||
308 | * must also be careful not to hold other locks that will deadlock | ||
309 | * against a discipline change, such as an existing ldisc reference | ||
310 | * (which we check for) | ||
311 | * | ||
312 | * Locking: call functions take tty_ldisc_lock | ||
313 | */ | ||
314 | |||
315 | struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | ||
316 | { | ||
317 | /* wait_event is a macro */ | ||
318 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | ||
319 | if (tty->ldisc.refcount == 0) | ||
320 | printk(KERN_ERR "tty_ldisc_ref_wait\n"); | ||
321 | return &tty->ldisc; | ||
322 | } | ||
323 | |||
324 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | ||
325 | |||
326 | /** | ||
327 | * tty_ldisc_ref - get the tty ldisc | ||
328 | * @tty: tty device | ||
329 | * | ||
330 | * Dereference the line discipline for the terminal and take a | ||
331 | * reference to it. If the line discipline is in flux then | ||
332 | * return NULL. Can be called from IRQ and timer functions. | ||
333 | * | ||
334 | * Locking: called functions take tty_ldisc_lock | ||
335 | */ | ||
336 | |||
337 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | ||
338 | { | ||
339 | if (tty_ldisc_try(tty)) | ||
340 | return &tty->ldisc; | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | ||
345 | |||
346 | /** | ||
347 | * tty_ldisc_deref - free a tty ldisc reference | ||
348 | * @ld: reference to free up | ||
349 | * | ||
350 | * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May | ||
351 | * be called in IRQ context. | ||
352 | * | ||
353 | * Locking: takes tty_ldisc_lock | ||
354 | */ | ||
355 | |||
356 | void tty_ldisc_deref(struct tty_ldisc *ld) | ||
357 | { | ||
358 | unsigned long flags; | ||
359 | |||
360 | BUG_ON(ld == NULL); | ||
361 | |||
362 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
363 | if (ld->refcount == 0) | ||
364 | printk(KERN_ERR "tty_ldisc_deref: no references.\n"); | ||
365 | else | ||
366 | ld->refcount--; | ||
367 | if (ld->refcount == 0) | ||
368 | wake_up(&tty_ldisc_wait); | ||
369 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
370 | } | ||
371 | |||
372 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | ||
373 | |||
374 | /** | ||
375 | * tty_ldisc_enable - allow ldisc use | ||
376 | * @tty: terminal to activate ldisc on | ||
377 | * | ||
378 | * Set the TTY_LDISC flag when the line discipline can be called | ||
379 | * again. Do necessary wakeups for existing sleepers. | ||
380 | * | ||
381 | * Note: nobody should set this bit except via this function. Clearing | ||
382 | * directly is allowed. | ||
383 | */ | ||
384 | |||
385 | void tty_ldisc_enable(struct tty_struct *tty) | ||
386 | { | ||
387 | set_bit(TTY_LDISC, &tty->flags); | ||
388 | wake_up(&tty_ldisc_wait); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * tty_set_termios_ldisc - set ldisc field | ||
393 | * @tty: tty structure | ||
394 | * @num: line discipline number | ||
395 | * | ||
396 | * This is probably overkill for real world processors but | ||
397 | * they are not on hot paths so a little discipline won't do | ||
398 | * any harm. | ||
399 | * | ||
400 | * Locking: takes termios_mutex | ||
401 | */ | ||
402 | |||
403 | static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | ||
404 | { | ||
405 | mutex_lock(&tty->termios_mutex); | ||
406 | tty->termios->c_line = num; | ||
407 | mutex_unlock(&tty->termios_mutex); | ||
408 | } | ||
409 | |||
410 | |||
411 | /** | ||
412 | * tty_ldisc_restore - helper for tty ldisc change | ||
413 | * @tty: tty to recover | ||
414 | * @old: previous ldisc | ||
415 | * | ||
416 | * Restore the previous line discipline or N_TTY when a line discipline | ||
417 | * change fails due to an open error | ||
418 | */ | ||
419 | |||
420 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | ||
421 | { | ||
422 | char buf[64]; | ||
423 | struct tty_ldisc new_ldisc; | ||
424 | |||
425 | /* There is an outstanding reference here so this is safe */ | ||
426 | tty_ldisc_get(old->ops->num, old); | ||
427 | tty_ldisc_assign(tty, old); | ||
428 | tty_set_termios_ldisc(tty, old->ops->num); | ||
429 | if (old->ops->open && (old->ops->open(tty) < 0)) { | ||
430 | tty_ldisc_put(old->ops); | ||
431 | /* This driver is always present */ | ||
432 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | ||
433 | panic("n_tty: get"); | ||
434 | tty_ldisc_assign(tty, &new_ldisc); | ||
435 | tty_set_termios_ldisc(tty, N_TTY); | ||
436 | if (new_ldisc.ops->open) { | ||
437 | int r = new_ldisc.ops->open(tty); | ||
438 | if (r < 0) | ||
439 | panic("Couldn't open N_TTY ldisc for " | ||
440 | "%s --- error %d.", | ||
441 | tty_name(tty, buf), r); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * tty_set_ldisc - set line discipline | ||
448 | * @tty: the terminal to set | ||
449 | * @ldisc: the line discipline | ||
450 | * | ||
451 | * Set the discipline of a tty line. Must be called from a process | ||
452 | * context. | ||
453 | * | ||
454 | * Locking: takes tty_ldisc_lock. | ||
455 | * called functions take termios_mutex | ||
456 | */ | ||
457 | |||
458 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) | ||
459 | { | ||
460 | int retval; | ||
461 | struct tty_ldisc o_ldisc, new_ldisc; | ||
462 | int work; | ||
463 | unsigned long flags; | ||
464 | struct tty_struct *o_tty; | ||
465 | |||
466 | restart: | ||
467 | /* This is a bit ugly for now but means we can break the 'ldisc | ||
468 | is part of the tty struct' assumption later */ | ||
469 | retval = tty_ldisc_get(ldisc, &new_ldisc); | ||
470 | if (retval) | ||
471 | return retval; | ||
472 | |||
473 | /* | ||
474 | * Problem: What do we do if this blocks ? | ||
475 | */ | ||
476 | |||
477 | tty_wait_until_sent(tty, 0); | ||
478 | |||
479 | if (tty->ldisc.ops->num == ldisc) { | ||
480 | tty_ldisc_put(new_ldisc.ops); | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * No more input please, we are switching. The new ldisc | ||
486 | * will update this value in the ldisc open function | ||
487 | */ | ||
488 | |||
489 | tty->receive_room = 0; | ||
490 | |||
491 | o_ldisc = tty->ldisc; | ||
492 | o_tty = tty->link; | ||
493 | |||
494 | /* | ||
495 | * Make sure we don't change while someone holds a | ||
496 | * reference to the line discipline. The TTY_LDISC bit | ||
497 | * prevents anyone taking a reference once it is clear. | ||
498 | * We need the lock to avoid racing reference takers. | ||
499 | */ | ||
500 | |||
501 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
502 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | ||
503 | if (tty->ldisc.refcount) { | ||
504 | /* Free the new ldisc we grabbed. Must drop the lock | ||
505 | first. */ | ||
506 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
507 | tty_ldisc_put(o_ldisc.ops); | ||
508 | /* | ||
509 | * There are several reasons we may be busy, including | ||
510 | * random momentary I/O traffic. We must therefore | ||
511 | * retry. We could distinguish between blocking ops | ||
512 | * and retries if we made tty_ldisc_wait() smarter. | ||
513 | * That is up for discussion. | ||
514 | */ | ||
515 | if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) | ||
516 | return -ERESTARTSYS; | ||
517 | goto restart; | ||
518 | } | ||
519 | if (o_tty && o_tty->ldisc.refcount) { | ||
520 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
521 | tty_ldisc_put(o_tty->ldisc.ops); | ||
522 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | ||
523 | return -ERESTARTSYS; | ||
524 | goto restart; | ||
525 | } | ||
526 | } | ||
527 | /* | ||
528 | * If the TTY_LDISC bit is set, then we are racing against | ||
529 | * another ldisc change | ||
530 | */ | ||
531 | if (!test_bit(TTY_LDISC, &tty->flags)) { | ||
532 | struct tty_ldisc *ld; | ||
533 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
534 | tty_ldisc_put(new_ldisc.ops); | ||
535 | ld = tty_ldisc_ref_wait(tty); | ||
536 | tty_ldisc_deref(ld); | ||
537 | goto restart; | ||
538 | } | ||
539 | |||
540 | clear_bit(TTY_LDISC, &tty->flags); | ||
541 | if (o_tty) | ||
542 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
543 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
544 | |||
545 | /* | ||
546 | * From this point on we know nobody has an ldisc | ||
547 | * usage reference, nor can they obtain one until | ||
548 | * we say so later on. | ||
549 | */ | ||
550 | |||
551 | work = cancel_delayed_work(&tty->buf.work); | ||
552 | /* | ||
553 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
554 | * MUST NOT hold locks here. | ||
555 | */ | ||
556 | flush_scheduled_work(); | ||
557 | /* Shutdown the current discipline. */ | ||
558 | if (o_ldisc.ops->close) | ||
559 | (o_ldisc.ops->close)(tty); | ||
560 | |||
561 | /* Now set up the new line discipline. */ | ||
562 | tty_ldisc_assign(tty, &new_ldisc); | ||
563 | tty_set_termios_ldisc(tty, ldisc); | ||
564 | if (new_ldisc.ops->open) | ||
565 | retval = (new_ldisc.ops->open)(tty); | ||
566 | if (retval < 0) { | ||
567 | tty_ldisc_put(new_ldisc.ops); | ||
568 | tty_ldisc_restore(tty, &o_ldisc); | ||
569 | } | ||
570 | /* At this point we hold a reference to the new ldisc and a | ||
571 | a reference to the old ldisc. If we ended up flipping back | ||
572 | to the existing ldisc we have two references to it */ | ||
573 | |||
574 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) | ||
575 | tty->ops->set_ldisc(tty); | ||
576 | |||
577 | tty_ldisc_put(o_ldisc.ops); | ||
578 | |||
579 | /* | ||
580 | * Allow ldisc referencing to occur as soon as the driver | ||
581 | * ldisc callback completes. | ||
582 | */ | ||
583 | |||
584 | tty_ldisc_enable(tty); | ||
585 | if (o_tty) | ||
586 | tty_ldisc_enable(o_tty); | ||
587 | |||
588 | /* Restart it in case no characters kick it off. Safe if | ||
589 | already running */ | ||
590 | if (work) | ||
591 | schedule_delayed_work(&tty->buf.work, 1); | ||
592 | return retval; | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * tty_ldisc_setup - open line discipline | ||
598 | * @tty: tty being shut down | ||
599 | * @o_tty: pair tty for pty/tty pairs | ||
600 | * | ||
601 | * Called during the initial open of a tty/pty pair in order to set up the | ||
602 | * line discplines and bind them to the tty. | ||
603 | */ | ||
604 | |||
605 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | ||
606 | { | ||
607 | struct tty_ldisc *ld = &tty->ldisc; | ||
608 | int retval; | ||
609 | |||
610 | if (ld->ops->open) { | ||
611 | retval = (ld->ops->open)(tty); | ||
612 | if (retval) | ||
613 | return retval; | ||
614 | } | ||
615 | if (o_tty && o_tty->ldisc.ops->open) { | ||
616 | retval = (o_tty->ldisc.ops->open)(o_tty); | ||
617 | if (retval) { | ||
618 | if (ld->ops->close) | ||
619 | (ld->ops->close)(tty); | ||
620 | return retval; | ||
621 | } | ||
622 | tty_ldisc_enable(o_tty); | ||
623 | } | ||
624 | tty_ldisc_enable(tty); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * tty_ldisc_release - release line discipline | ||
630 | * @tty: tty being shut down | ||
631 | * @o_tty: pair tty for pty/tty pairs | ||
632 | * | ||
633 | * Called during the final close of a tty/pty pair in order to shut down the | ||
634 | * line discpline layer. | ||
635 | */ | ||
636 | |||
637 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | ||
638 | { | ||
639 | unsigned long flags; | ||
640 | struct tty_ldisc ld; | ||
641 | /* | ||
642 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then | ||
643 | * kill any delayed work. As this is the final close it does not | ||
644 | * race with the set_ldisc code path. | ||
645 | */ | ||
646 | clear_bit(TTY_LDISC, &tty->flags); | ||
647 | cancel_delayed_work(&tty->buf.work); | ||
648 | |||
649 | /* | ||
650 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
651 | */ | ||
652 | |||
653 | flush_scheduled_work(); | ||
654 | |||
655 | /* | ||
656 | * Wait for any short term users (we know they are just driver | ||
657 | * side waiters as the file is closing so user count on the file | ||
658 | * side is zero. | ||
659 | */ | ||
660 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
661 | while (tty->ldisc.refcount) { | ||
662 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
663 | wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); | ||
664 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
665 | } | ||
666 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
667 | /* | ||
668 | * Shutdown the current line discipline, and reset it to N_TTY. | ||
669 | * | ||
670 | * FIXME: this MUST get fixed for the new reflocking | ||
671 | */ | ||
672 | if (tty->ldisc.ops->close) | ||
673 | (tty->ldisc.ops->close)(tty); | ||
674 | tty_ldisc_put(tty->ldisc.ops); | ||
675 | |||
676 | /* | ||
677 | * Switch the line discipline back | ||
678 | */ | ||
679 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
680 | tty_ldisc_assign(tty, &ld); | ||
681 | tty_set_termios_ldisc(tty, N_TTY); | ||
682 | if (o_tty) { | ||
683 | /* FIXME: could o_tty be in setldisc here ? */ | ||
684 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
685 | if (o_tty->ldisc.ops->close) | ||
686 | (o_tty->ldisc.ops->close)(o_tty); | ||
687 | tty_ldisc_put(o_tty->ldisc.ops); | ||
688 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
689 | tty_ldisc_assign(o_tty, &ld); | ||
690 | tty_set_termios_ldisc(o_tty, N_TTY); | ||
691 | } | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * tty_ldisc_init - ldisc setup for new tty | ||
696 | * @tty: tty being allocated | ||
697 | * | ||
698 | * Set up the line discipline objects for a newly allocated tty. Note that | ||
699 | * the tty structure is not completely set up when this call is made. | ||
700 | */ | ||
701 | |||
702 | void tty_ldisc_init(struct tty_struct *tty) | ||
703 | { | ||
704 | struct tty_ldisc ld; | ||
705 | if (tty_ldisc_get(N_TTY, &ld) < 0) | ||
706 | panic("n_tty: init_tty"); | ||
707 | tty_ldisc_assign(tty, &ld); | ||
708 | } | ||
709 | |||
710 | void tty_ldisc_begin(void) | ||
711 | { | ||
712 | /* Setup the default TTY line discipline. */ | ||
713 | (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); | ||
714 | } | ||
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index eebfad2777d2..c2ae52dd53d1 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -481,10 +481,10 @@ static struct class *vc_class; | |||
481 | 481 | ||
482 | void vcs_make_sysfs(struct tty_struct *tty) | 482 | void vcs_make_sysfs(struct tty_struct *tty) |
483 | { | 483 | { |
484 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), | 484 | device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), |
485 | "vcs%u", tty->index + 1); | 485 | NULL, "vcs%u", tty->index + 1); |
486 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), | 486 | device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), |
487 | "vcsa%u", tty->index + 1); | 487 | NULL, "vcsa%u", tty->index + 1); |
488 | } | 488 | } |
489 | 489 | ||
490 | void vcs_remove_sysfs(struct tty_struct *tty) | 490 | void vcs_remove_sysfs(struct tty_struct *tty) |
@@ -499,7 +499,7 @@ int __init vcs_init(void) | |||
499 | panic("unable to get major %d for vcs device", VCS_MAJOR); | 499 | panic("unable to get major %d for vcs device", VCS_MAJOR); |
500 | vc_class = class_create(THIS_MODULE, "vc"); | 500 | vc_class = class_create(THIS_MODULE, "vc"); |
501 | 501 | ||
502 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs"); | 502 | device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); |
503 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa"); | 503 | device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); |
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index e5da98d8f9cd..7a70a40ad639 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
886 | state[i].cur_part = 0; | 886 | state[i].cur_part = 0; |
887 | for (j = 0; j < MAX_PARTITIONS; ++j) | 887 | for (j = 0; j < MAX_PARTITIONS; ++j) |
888 | state[i].part_stat_rwi[j] = VIOT_IDLE; | 888 | state[i].part_stat_rwi[j] = VIOT_IDLE; |
889 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), | 889 | device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), |
890 | "iseries!vt%d", i); | 890 | NULL, "iseries!vt%d", i); |
891 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), | 891 | device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), |
892 | "iseries!nvt%d", i); | 892 | NULL, "iseries!nvt%d", i); |
893 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " | 893 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " |
894 | "resource %10.10s type %4.4s, model %3.3s\n", | 894 | "resource %10.10s type %4.4s, model %3.3s\n", |
895 | i, viotape_unitinfo[i].rsrcname, | 895 | i, viotape_unitinfo[i].rsrcname, |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index dc17fe3a88bc..d0f4eb6fdb7f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -46,6 +46,9 @@ static char *in, *inbuf; | |||
46 | /* The operations for our console. */ | 46 | /* The operations for our console. */ |
47 | static struct hv_ops virtio_cons; | 47 | static struct hv_ops virtio_cons; |
48 | 48 | ||
49 | /* The hvc device */ | ||
50 | static struct hvc_struct *hvc; | ||
51 | |||
49 | /*D:310 The put_chars() callback is pretty straightforward. | 52 | /*D:310 The put_chars() callback is pretty straightforward. |
50 | * | 53 | * |
51 | * We turn the characters into a scatter-gather list, add it to the output | 54 | * 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)) | |||
134 | return hvc_instantiate(0, 0, &virtio_cons); | 137 | return hvc_instantiate(0, 0, &virtio_cons); |
135 | } | 138 | } |
136 | 139 | ||
140 | /* | ||
141 | * we support only one console, the hvc struct is a global var | ||
142 | * There is no need to do anything | ||
143 | */ | ||
144 | static int notifier_add_vio(struct hvc_struct *hp, int data) | ||
145 | { | ||
146 | hp->irq_requested = 1; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void notifier_del_vio(struct hvc_struct *hp, int data) | ||
151 | { | ||
152 | hp->irq_requested = 0; | ||
153 | } | ||
154 | |||
155 | static void hvc_handle_input(struct virtqueue *vq) | ||
156 | { | ||
157 | if (hvc_poll(hvc)) | ||
158 | hvc_kick(); | ||
159 | } | ||
160 | |||
137 | /*D:370 Once we're further in boot, we get probed like any other virtio device. | 161 | /*D:370 Once we're further in boot, we get probed like any other virtio device. |
138 | * At this stage we set up the output virtqueue. | 162 | * At this stage we set up the output virtqueue. |
139 | * | 163 | * |
@@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
144 | static int __devinit virtcons_probe(struct virtio_device *dev) | 168 | static int __devinit virtcons_probe(struct virtio_device *dev) |
145 | { | 169 | { |
146 | int err; | 170 | int err; |
147 | struct hvc_struct *hvc; | ||
148 | 171 | ||
149 | vdev = dev; | 172 | vdev = dev; |
150 | 173 | ||
@@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
158 | /* Find the input queue. */ | 181 | /* Find the input queue. */ |
159 | /* FIXME: This is why we want to wean off hvc: we do nothing | 182 | /* FIXME: This is why we want to wean off hvc: we do nothing |
160 | * when input comes in. */ | 183 | * when input comes in. */ |
161 | in_vq = vdev->config->find_vq(vdev, 0, NULL); | 184 | in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input); |
162 | if (IS_ERR(in_vq)) { | 185 | if (IS_ERR(in_vq)) { |
163 | err = PTR_ERR(in_vq); | 186 | err = PTR_ERR(in_vq); |
164 | goto free; | 187 | goto free; |
@@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
173 | /* Start using the new console output. */ | 196 | /* Start using the new console output. */ |
174 | virtio_cons.get_chars = get_chars; | 197 | virtio_cons.get_chars = get_chars; |
175 | virtio_cons.put_chars = put_chars; | 198 | virtio_cons.put_chars = put_chars; |
199 | virtio_cons.notifier_add = notifier_add_vio; | ||
200 | virtio_cons.notifier_del = notifier_del_vio; | ||
176 | 201 | ||
177 | /* The first argument of hvc_alloc() is the virtual console number, so | 202 | /* The first argument of hvc_alloc() is the virtual console number, so |
178 | * we use zero. The second argument is the interrupt number; we | 203 | * we use zero. The second argument is the parameter for the |
179 | * currently leave this as zero: it would be better not to use the | 204 | * notification mechanism (like irq number). We currently leave this |
180 | * hvc mechanism and fix this (FIXME!). | 205 | * as zero, virtqueues have implicit notifications. |
181 | * | 206 | * |
182 | * The third argument is a "struct hv_ops" containing the put_chars() | 207 | * The third argument is a "struct hv_ops" containing the put_chars() |
183 | * and get_chars() pointers. The final argument is the output buffer | 208 | * get_chars(), notifier_add() and notifier_del() pointers. |
184 | * size: we can do any size, so we put PAGE_SIZE here. */ | 209 | * The final argument is the output buffer size: we can do any size, |
210 | * so we put PAGE_SIZE here. */ | ||
185 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); | 211 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); |
186 | if (IS_ERR(hvc)) { | 212 | if (IS_ERR(hvc)) { |
187 | err = PTR_ERR(hvc); | 213 | err = PTR_ERR(hvc); |
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index f17ac043b551..1718b3c481db 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c | |||
@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data); | |||
85 | static irqreturn_t scc_stat_int(int irq, void *data); | 85 | static irqreturn_t scc_stat_int(int irq, void *data); |
86 | static irqreturn_t scc_spcond_int(int irq, void *data); | 86 | static irqreturn_t scc_spcond_int(int irq, void *data); |
87 | static void scc_setsignals(struct scc_port *port, int dtr, int rts); | 87 | static void scc_setsignals(struct scc_port *port, int dtr, int rts); |
88 | static void scc_break_ctl(struct tty_struct *tty, int break_state); | 88 | static int scc_break_ctl(struct tty_struct *tty, int break_state); |
89 | 89 | ||
90 | static struct tty_driver *scc_driver; | 90 | static struct tty_driver *scc_driver; |
91 | 91 | ||
@@ -183,8 +183,8 @@ static void scc_init_portstructs(void) | |||
183 | #ifdef NEW_WRITE_LOCKING | 183 | #ifdef NEW_WRITE_LOCKING |
184 | port->gs.port_write_mutex = MUTEX; | 184 | port->gs.port_write_mutex = MUTEX; |
185 | #endif | 185 | #endif |
186 | init_waitqueue_head(&port->gs.open_wait); | 186 | init_waitqueue_head(&port->gs.port.open_wait); |
187 | init_waitqueue_head(&port->gs.close_wait); | 187 | init_waitqueue_head(&port->gs.port.close_wait); |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
@@ -422,7 +422,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) | |||
422 | { | 422 | { |
423 | unsigned char ch; | 423 | unsigned char ch; |
424 | struct scc_port *port = data; | 424 | struct scc_port *port = data; |
425 | struct tty_struct *tty = port->gs.tty; | 425 | struct tty_struct *tty = port->gs.port.tty; |
426 | SCC_ACCESS_INIT(port); | 426 | SCC_ACCESS_INIT(port); |
427 | 427 | ||
428 | ch = SCCread_NB(RX_DATA_REG); | 428 | ch = SCCread_NB(RX_DATA_REG); |
@@ -453,7 +453,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) | |||
453 | static irqreturn_t scc_spcond_int(int irq, void *data) | 453 | static irqreturn_t scc_spcond_int(int irq, void *data) |
454 | { | 454 | { |
455 | struct scc_port *port = data; | 455 | struct scc_port *port = data; |
456 | struct tty_struct *tty = port->gs.tty; | 456 | struct tty_struct *tty = port->gs.port.tty; |
457 | unsigned char stat, ch, err; | 457 | unsigned char stat, ch, err; |
458 | int int_pending_mask = port->channel == CHANNEL_A ? | 458 | int int_pending_mask = port->channel == CHANNEL_A ? |
459 | IPR_A_RX : IPR_B_RX; | 459 | IPR_A_RX : IPR_B_RX; |
@@ -500,7 +500,7 @@ static irqreturn_t scc_tx_int(int irq, void *data) | |||
500 | struct scc_port *port = data; | 500 | struct scc_port *port = data; |
501 | SCC_ACCESS_INIT(port); | 501 | SCC_ACCESS_INIT(port); |
502 | 502 | ||
503 | if (!port->gs.tty) { | 503 | if (!port->gs.port.tty) { |
504 | printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); | 504 | printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); |
505 | SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); | 505 | SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); |
506 | SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); | 506 | SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); |
@@ -512,8 +512,9 @@ static irqreturn_t scc_tx_int(int irq, void *data) | |||
512 | SCCwrite(TX_DATA_REG, port->x_char); | 512 | SCCwrite(TX_DATA_REG, port->x_char); |
513 | port->x_char = 0; | 513 | port->x_char = 0; |
514 | } | 514 | } |
515 | else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || | 515 | else if ((port->gs.xmit_cnt <= 0) || |
516 | port->gs.tty->hw_stopped) | 516 | port->gs.port.tty->stopped || |
517 | port->gs.port.tty->hw_stopped) | ||
517 | break; | 518 | break; |
518 | else { | 519 | else { |
519 | SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); | 520 | 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) | |||
522 | break; | 523 | break; |
523 | } | 524 | } |
524 | } | 525 | } |
525 | if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || | 526 | if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped || |
526 | port->gs.tty->hw_stopped) { | 527 | port->gs.port.tty->hw_stopped) { |
527 | /* disable tx interrupts */ | 528 | /* disable tx interrupts */ |
528 | SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); | 529 | SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); |
529 | SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ | 530 | SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ |
530 | port->gs.flags &= ~GS_TX_INTEN; | 531 | port->gs.port.flags &= ~GS_TX_INTEN; |
531 | } | 532 | } |
532 | if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) | 533 | if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) |
533 | tty_wakeup(port->gs.tty); | 534 | tty_wakeup(port->gs.port.tty); |
534 | 535 | ||
535 | SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); | 536 | SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); |
536 | return IRQ_HANDLED; | 537 | return IRQ_HANDLED; |
@@ -550,14 +551,14 @@ static irqreturn_t scc_stat_int(int irq, void *data) | |||
550 | 551 | ||
551 | if (changed & SR_DCD) { | 552 | if (changed & SR_DCD) { |
552 | port->c_dcd = !!(sr & SR_DCD); | 553 | port->c_dcd = !!(sr & SR_DCD); |
553 | if (!(port->gs.flags & ASYNC_CHECK_CD)) | 554 | if (!(port->gs.port.flags & ASYNC_CHECK_CD)) |
554 | ; /* Don't report DCD changes */ | 555 | ; /* Don't report DCD changes */ |
555 | else if (port->c_dcd) { | 556 | else if (port->c_dcd) { |
556 | wake_up_interruptible(&port->gs.open_wait); | 557 | wake_up_interruptible(&port->gs.port.open_wait); |
557 | } | 558 | } |
558 | else { | 559 | else { |
559 | if (port->gs.tty) | 560 | if (port->gs.port.tty) |
560 | tty_hangup (port->gs.tty); | 561 | tty_hangup (port->gs.port.tty); |
561 | } | 562 | } |
562 | } | 563 | } |
563 | SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); | 564 | SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); |
@@ -578,7 +579,7 @@ static void scc_disable_tx_interrupts(void *ptr) | |||
578 | 579 | ||
579 | local_irq_save(flags); | 580 | local_irq_save(flags); |
580 | SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); | 581 | SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); |
581 | port->gs.flags &= ~GS_TX_INTEN; | 582 | port->gs.port.flags &= ~GS_TX_INTEN; |
582 | local_irq_restore(flags); | 583 | local_irq_restore(flags); |
583 | } | 584 | } |
584 | 585 | ||
@@ -636,8 +637,8 @@ static void scc_shutdown_port(void *ptr) | |||
636 | { | 637 | { |
637 | struct scc_port *port = ptr; | 638 | struct scc_port *port = ptr; |
638 | 639 | ||
639 | port->gs.flags &= ~ GS_ACTIVE; | 640 | port->gs.port.flags &= ~ GS_ACTIVE; |
640 | if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { | 641 | if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { |
641 | scc_setsignals (port, 0, 0); | 642 | scc_setsignals (port, 0, 0); |
642 | } | 643 | } |
643 | } | 644 | } |
@@ -652,14 +653,14 @@ static int scc_set_real_termios (void *ptr) | |||
652 | struct scc_port *port = ptr; | 653 | struct scc_port *port = ptr; |
653 | SCC_ACCESS_INIT(port); | 654 | SCC_ACCESS_INIT(port); |
654 | 655 | ||
655 | if (!port->gs.tty || !port->gs.tty->termios) return 0; | 656 | if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; |
656 | 657 | ||
657 | channel = port->channel; | 658 | channel = port->channel; |
658 | 659 | ||
659 | if (channel == CHANNEL_A) | 660 | if (channel == CHANNEL_A) |
660 | return 0; /* Settings controlled by boot PROM */ | 661 | return 0; /* Settings controlled by boot PROM */ |
661 | 662 | ||
662 | cflag = port->gs.tty->termios->c_cflag; | 663 | cflag = port->gs.port.tty->termios->c_cflag; |
663 | baud = port->gs.baud; | 664 | baud = port->gs.baud; |
664 | chsize = (cflag & CSIZE) >> 4; | 665 | chsize = (cflag & CSIZE) >> 4; |
665 | 666 | ||
@@ -678,9 +679,9 @@ static int scc_set_real_termios (void *ptr) | |||
678 | } | 679 | } |
679 | 680 | ||
680 | if (cflag & CLOCAL) | 681 | if (cflag & CLOCAL) |
681 | port->gs.flags &= ~ASYNC_CHECK_CD; | 682 | port->gs.port.flags &= ~ASYNC_CHECK_CD; |
682 | else | 683 | else |
683 | port->gs.flags |= ASYNC_CHECK_CD; | 684 | port->gs.port.flags |= ASYNC_CHECK_CD; |
684 | 685 | ||
685 | #ifdef CONFIG_MVME147_SCC | 686 | #ifdef CONFIG_MVME147_SCC |
686 | if (MACH_IS_MVME147) | 687 | if (MACH_IS_MVME147) |
@@ -856,7 +857,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) | |||
856 | { COMMAND_REG, CR_EXTSTAT_RESET }, | 857 | { COMMAND_REG, CR_EXTSTAT_RESET }, |
857 | }; | 858 | }; |
858 | #endif | 859 | #endif |
859 | if (!(port->gs.flags & ASYNC_INITIALIZED)) { | 860 | if (!(port->gs.port.flags & ASYNC_INITIALIZED)) { |
860 | local_irq_save(flags); | 861 | local_irq_save(flags); |
861 | #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) | 862 | #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) |
862 | if (MACH_IS_MVME147 || MACH_IS_MVME16x) { | 863 | if (MACH_IS_MVME147 || MACH_IS_MVME16x) { |
@@ -880,18 +881,18 @@ static int scc_open (struct tty_struct * tty, struct file * filp) | |||
880 | } | 881 | } |
881 | 882 | ||
882 | tty->driver_data = port; | 883 | tty->driver_data = port; |
883 | port->gs.tty = tty; | 884 | port->gs.port.tty = tty; |
884 | port->gs.count++; | 885 | port->gs.port.count++; |
885 | retval = gs_init_port(&port->gs); | 886 | retval = gs_init_port(&port->gs); |
886 | if (retval) { | 887 | if (retval) { |
887 | port->gs.count--; | 888 | port->gs.port.count--; |
888 | return retval; | 889 | return retval; |
889 | } | 890 | } |
890 | port->gs.flags |= GS_ACTIVE; | 891 | port->gs.port.flags |= GS_ACTIVE; |
891 | retval = gs_block_til_ready(port, filp); | 892 | retval = gs_block_til_ready(port, filp); |
892 | 893 | ||
893 | if (retval) { | 894 | if (retval) { |
894 | port->gs.count--; | 895 | port->gs.port.count--; |
895 | return retval; | 896 | return retval; |
896 | } | 897 | } |
897 | 898 | ||
@@ -942,7 +943,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file, | |||
942 | } | 943 | } |
943 | 944 | ||
944 | 945 | ||
945 | static void scc_break_ctl(struct tty_struct *tty, int break_state) | 946 | static int scc_break_ctl(struct tty_struct *tty, int break_state) |
946 | { | 947 | { |
947 | struct scc_port *port = (struct scc_port *)tty->driver_data; | 948 | struct scc_port *port = (struct scc_port *)tty->driver_data; |
948 | unsigned long flags; | 949 | unsigned long flags; |
@@ -952,6 +953,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state) | |||
952 | SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, | 953 | SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, |
953 | break_state ? TCR_SEND_BREAK : 0); | 954 | break_state ? TCR_SEND_BREAK : 0); |
954 | local_irq_restore(flags); | 955 | local_irq_restore(flags); |
956 | return 0; | ||
955 | } | 957 | } |
956 | 958 | ||
957 | 959 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 935f1c207a1f..1bc00c9d860d 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -261,7 +261,7 @@ static void notify_update(struct vc_data *vc) | |||
261 | #ifdef VT_BUF_VRAM_ONLY | 261 | #ifdef VT_BUF_VRAM_ONLY |
262 | #define DO_UPDATE(vc) 0 | 262 | #define DO_UPDATE(vc) 0 |
263 | #else | 263 | #else |
264 | #define DO_UPDATE(vc) CON_IS_VISIBLE(vc) | 264 | #define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked) |
265 | #endif | 265 | #endif |
266 | 266 | ||
267 | static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed) | 267 | static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed) |
@@ -916,7 +916,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
916 | ws.ws_col = vc->vc_cols; | 916 | ws.ws_col = vc->vc_cols; |
917 | ws.ws_ypixel = vc->vc_scan_lines; | 917 | ws.ws_ypixel = vc->vc_scan_lines; |
918 | 918 | ||
919 | mutex_lock(&vc->vc_tty->termios_mutex); | ||
920 | spin_lock_irq(&vc->vc_tty->ctrl_lock); | 919 | spin_lock_irq(&vc->vc_tty->ctrl_lock); |
921 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) | 920 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) |
922 | pgrp = get_pid(vc->vc_tty->pgrp); | 921 | pgrp = get_pid(vc->vc_tty->pgrp); |
@@ -926,7 +925,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
926 | put_pid(pgrp); | 925 | put_pid(pgrp); |
927 | } | 926 | } |
928 | *cws = ws; | 927 | *cws = ws; |
929 | mutex_unlock(&vc->vc_tty->termios_mutex); | ||
930 | } | 928 | } |
931 | 929 | ||
932 | if (CON_IS_VISIBLE(vc)) | 930 | if (CON_IS_VISIBLE(vc)) |
@@ -2211,7 +2209,7 @@ rescan_last_byte: | |||
2211 | c = 0xfffd; | 2209 | c = 0xfffd; |
2212 | tc = c; | 2210 | tc = c; |
2213 | } else { /* no utf or alternate charset mode */ | 2211 | } else { /* no utf or alternate charset mode */ |
2214 | tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; | 2212 | tc = vc_translate(vc, c); |
2215 | } | 2213 | } |
2216 | 2214 | ||
2217 | param.c = tc; | 2215 | param.c = tc; |
@@ -2749,8 +2747,8 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2749 | tty->termios->c_iflag |= IUTF8; | 2747 | tty->termios->c_iflag |= IUTF8; |
2750 | else | 2748 | else |
2751 | tty->termios->c_iflag &= ~IUTF8; | 2749 | tty->termios->c_iflag &= ~IUTF8; |
2752 | release_console_sem(); | ||
2753 | vcs_make_sysfs(tty); | 2750 | vcs_make_sysfs(tty); |
2751 | release_console_sem(); | ||
2754 | return ret; | 2752 | return ret; |
2755 | } | 2753 | } |
2756 | } | 2754 | } |
@@ -2775,8 +2773,8 @@ static void con_close(struct tty_struct *tty, struct file *filp) | |||
2775 | if (vc) | 2773 | if (vc) |
2776 | vc->vc_tty = NULL; | 2774 | vc->vc_tty = NULL; |
2777 | tty->driver_data = NULL; | 2775 | tty->driver_data = NULL; |
2778 | release_console_sem(); | ||
2779 | vcs_remove_sysfs(tty); | 2776 | vcs_remove_sysfs(tty); |
2777 | release_console_sem(); | ||
2780 | mutex_unlock(&tty_mutex); | 2778 | mutex_unlock(&tty_mutex); |
2781 | /* | 2779 | /* |
2782 | * tty_mutex is released, but we still hold BKL, so there is | 2780 | * tty_mutex is released, but we still hold BKL, so there is |
@@ -3425,9 +3423,10 @@ int register_con_driver(const struct consw *csw, int first, int last) | |||
3425 | if (retval) | 3423 | if (retval) |
3426 | goto err; | 3424 | goto err; |
3427 | 3425 | ||
3428 | con_driver->dev = device_create(vtconsole_class, NULL, | 3426 | con_driver->dev = device_create_drvdata(vtconsole_class, NULL, |
3429 | MKDEV(0, con_driver->node), | 3427 | MKDEV(0, con_driver->node), |
3430 | "vtcon%i", con_driver->node); | 3428 | NULL, "vtcon%i", |
3429 | con_driver->node); | ||
3431 | 3430 | ||
3432 | if (IS_ERR(con_driver->dev)) { | 3431 | if (IS_ERR(con_driver->dev)) { |
3433 | printk(KERN_WARNING "Unable to create device for %s; " | 3432 | printk(KERN_WARNING "Unable to create device for %s; " |
@@ -3535,9 +3534,10 @@ static int __init vtconsole_class_init(void) | |||
3535 | struct con_driver *con = ®istered_con_driver[i]; | 3534 | struct con_driver *con = ®istered_con_driver[i]; |
3536 | 3535 | ||
3537 | if (con->con && !con->dev) { | 3536 | if (con->con && !con->dev) { |
3538 | con->dev = device_create(vtconsole_class, NULL, | 3537 | con->dev = device_create_drvdata(vtconsole_class, NULL, |
3539 | MKDEV(0, con->node), | 3538 | MKDEV(0, con->node), |
3540 | "vtcon%i", con->node); | 3539 | NULL, "vtcon%i", |
3540 | con->node); | ||
3541 | 3541 | ||
3542 | if (IS_ERR(con->dev)) { | 3542 | if (IS_ERR(con->dev)) { |
3543 | printk(KERN_WARNING "Unable to create " | 3543 | printk(KERN_WARNING "Unable to create " |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 1e1b81e57cdc..8bfee5fb7223 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -87,7 +87,6 @@ | |||
87 | #include <linux/mutex.h> | 87 | #include <linux/mutex.h> |
88 | #include <linux/smp_lock.h> | 88 | #include <linux/smp_lock.h> |
89 | #include <linux/sysctl.h> | 89 | #include <linux/sysctl.h> |
90 | #include <linux/version.h> | ||
91 | #include <linux/fs.h> | 90 | #include <linux/fs.h> |
92 | #include <linux/cdev.h> | 91 | #include <linux/cdev.h> |
93 | #include <linux/platform_device.h> | 92 | #include <linux/platform_device.h> |
@@ -658,8 +657,9 @@ static int __devinit hwicap_setup(struct device *dev, int id, | |||
658 | dev_err(dev, "cdev_add() failed\n"); | 657 | dev_err(dev, "cdev_add() failed\n"); |
659 | goto failed3; | 658 | goto failed3; |
660 | } | 659 | } |
661 | /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ | 660 | |
662 | device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id); | 661 | device_create_drvdata(icap_class, dev, devt, NULL, |
662 | "%s%d", DRIVER_NAME, id); | ||
663 | return 0; /* success */ | 663 | return 0; /* success */ |
664 | 664 | ||
665 | failed3: | 665 | failed3: |