diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/agp/nvidia-agp.c | 3 | ||||
-rw-r--r-- | drivers/char/drm/drm_fops.c | 2 | ||||
-rw-r--r-- | drivers/char/drm/i810_dma.c | 2 | ||||
-rw-r--r-- | drivers/char/drm/i830_dma.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 4 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 7 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 6 | ||||
-rw-r--r-- | drivers/char/mem.c | 2 | ||||
-rw-r--r-- | drivers/char/misc.c | 2 | ||||
-rw-r--r-- | drivers/char/mxser.h | 2 | ||||
-rw-r--r-- | drivers/char/synclink.c | 33 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 250 |
13 files changed, 263 insertions, 54 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7a85b3a26ff8..889cad07774e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -713,7 +713,7 @@ config NVRAM | |||
713 | 713 | ||
714 | config RTC | 714 | config RTC |
715 | tristate "Enhanced Real Time Clock Support" | 715 | tristate "Enhanced Real Time Clock Support" |
716 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV | 716 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM |
717 | ---help--- | 717 | ---help--- |
718 | If you say Y here and create a character special file /dev/rtc with | 718 | If you say Y here and create a character special file /dev/rtc with |
719 | major number 10 and minor number 135 using mknod ("man mknod"), you | 719 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 70b8ed9cd172..4c67135c12d8 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/gfp.h> | 11 | #include <linux/gfp.h> |
12 | #include <linux/page-flags.h> | 12 | #include <linux/page-flags.h> |
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/jiffies.h> | ||
14 | #include "agp.h" | 15 | #include "agp.h" |
15 | 16 | ||
16 | /* NVIDIA registers */ | 17 | /* NVIDIA registers */ |
@@ -256,7 +257,7 @@ static void nvidia_tlbflush(struct agp_memory *mem) | |||
256 | do { | 257 | do { |
257 | pci_read_config_dword(nvidia_private.dev_1, | 258 | pci_read_config_dword(nvidia_private.dev_1, |
258 | NVIDIA_1_WBC, &wbc_reg); | 259 | NVIDIA_1_WBC, &wbc_reg); |
259 | if ((signed)(end - jiffies) <= 0) { | 260 | if (time_before_eq(end, jiffies)) { |
260 | printk(KERN_ERR PFX | 261 | printk(KERN_ERR PFX |
261 | "TLB flush took more than 3 seconds.\n"); | 262 | "TLB flush took more than 3 seconds.\n"); |
262 | } | 263 | } |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 641f7633878c..b7f7951c4587 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -175,7 +175,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) | |||
175 | drm_device_t *dev = NULL; | 175 | drm_device_t *dev = NULL; |
176 | int minor = iminor(inode); | 176 | int minor = iminor(inode); |
177 | int err = -ENODEV; | 177 | int err = -ENODEV; |
178 | struct file_operations *old_fops; | 178 | const struct file_operations *old_fops; |
179 | 179 | ||
180 | DRM_DEBUG("\n"); | 180 | DRM_DEBUG("\n"); |
181 | 181 | ||
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index ae0aa6d7e0bb..c658dde3633b 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -126,7 +126,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp) | |||
126 | drm_device_t *dev = priv->head->dev; | 126 | drm_device_t *dev = priv->head->dev; |
127 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; | 127 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; |
128 | drm_i810_private_t *dev_priv = dev->dev_private; | 128 | drm_i810_private_t *dev_priv = dev->dev_private; |
129 | struct file_operations *old_fops; | 129 | const struct file_operations *old_fops; |
130 | int retcode = 0; | 130 | int retcode = 0; |
131 | 131 | ||
132 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) | 132 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 163f2cbfe60d..b0f815d8cea8 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -128,7 +128,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp) | |||
128 | drm_device_t *dev = priv->head->dev; | 128 | drm_device_t *dev = priv->head->dev; |
129 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | 129 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; |
130 | drm_i830_private_t *dev_priv = dev->dev_private; | 130 | drm_i830_private_t *dev_priv = dev->dev_private; |
131 | struct file_operations *old_fops; | 131 | const struct file_operations *old_fops; |
132 | unsigned long virtual; | 132 | unsigned long virtual; |
133 | int retcode = 0; | 133 | int retcode = 0; |
134 | 134 | ||
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index b8fb87c6c29f..40eb005b9d77 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -3744,7 +3744,7 @@ static int ipmi_init_msghandler(void) | |||
3744 | ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES; | 3744 | ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES; |
3745 | add_timer(&ipmi_timer); | 3745 | add_timer(&ipmi_timer); |
3746 | 3746 | ||
3747 | notifier_chain_register(&panic_notifier_list, &panic_block); | 3747 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
3748 | 3748 | ||
3749 | initialized = 1; | 3749 | initialized = 1; |
3750 | 3750 | ||
@@ -3764,7 +3764,7 @@ static __exit void cleanup_ipmi(void) | |||
3764 | if (!initialized) | 3764 | if (!initialized) |
3765 | return; | 3765 | return; |
3766 | 3766 | ||
3767 | notifier_chain_unregister(&panic_notifier_list, &panic_block); | 3767 | atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); |
3768 | 3768 | ||
3769 | /* This can't be called if any interfaces exist, so no worry about | 3769 | /* This can't be called if any interfaces exist, so no worry about |
3770 | shutting down the interfaces. */ | 3770 | shutting down the interfaces. */ |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 12f858dc9994..35fbd4d8ed4b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -237,10 +237,10 @@ struct smi_info | |||
237 | 237 | ||
238 | static int try_smi_init(struct smi_info *smi); | 238 | static int try_smi_init(struct smi_info *smi); |
239 | 239 | ||
240 | static struct notifier_block *xaction_notifier_list; | 240 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); |
241 | static int register_xaction_notifier(struct notifier_block * nb) | 241 | static int register_xaction_notifier(struct notifier_block * nb) |
242 | { | 242 | { |
243 | return notifier_chain_register(&xaction_notifier_list, nb); | 243 | return atomic_notifier_chain_register(&xaction_notifier_list, nb); |
244 | } | 244 | } |
245 | 245 | ||
246 | static void si_restart_short_timer(struct smi_info *smi_info); | 246 | static void si_restart_short_timer(struct smi_info *smi_info); |
@@ -302,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
302 | do_gettimeofday(&t); | 302 | do_gettimeofday(&t); |
303 | printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 303 | printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
304 | #endif | 304 | #endif |
305 | err = notifier_call_chain(&xaction_notifier_list, 0, smi_info); | 305 | err = atomic_notifier_call_chain(&xaction_notifier_list, |
306 | 0, smi_info); | ||
306 | if (err & NOTIFY_STOP_MASK) { | 307 | if (err & NOTIFY_STOP_MASK) { |
307 | rv = SI_SM_CALL_WITHOUT_DELAY; | 308 | rv = SI_SM_CALL_WITHOUT_DELAY; |
308 | goto out; | 309 | goto out; |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 616539310d9a..7ece9f3c8f70 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -1158,7 +1158,8 @@ static int __init ipmi_wdog_init(void) | |||
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | register_reboot_notifier(&wdog_reboot_notifier); | 1160 | register_reboot_notifier(&wdog_reboot_notifier); |
1161 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); | 1161 | atomic_notifier_chain_register(&panic_notifier_list, |
1162 | &wdog_panic_notifier); | ||
1162 | 1163 | ||
1163 | printk(KERN_INFO PFX "driver initialized\n"); | 1164 | printk(KERN_INFO PFX "driver initialized\n"); |
1164 | 1165 | ||
@@ -1176,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void) | |||
1176 | release_nmi(&ipmi_nmi_handler); | 1177 | release_nmi(&ipmi_nmi_handler); |
1177 | #endif | 1178 | #endif |
1178 | 1179 | ||
1179 | notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); | 1180 | atomic_notifier_chain_unregister(&panic_notifier_list, |
1181 | &wdog_panic_notifier); | ||
1180 | unregister_reboot_notifier(&wdog_reboot_notifier); | 1182 | unregister_reboot_notifier(&wdog_reboot_notifier); |
1181 | 1183 | ||
1182 | if (! watchdog_user) | 1184 | if (! watchdog_user) |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5245ba1649ed..66719f9d294c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -899,7 +899,7 @@ static const struct { | |||
899 | unsigned int minor; | 899 | unsigned int minor; |
900 | char *name; | 900 | char *name; |
901 | umode_t mode; | 901 | umode_t mode; |
902 | struct file_operations *fops; | 902 | const struct file_operations *fops; |
903 | } devlist[] = { /* list of minor devices */ | 903 | } devlist[] = { /* list of minor devices */ |
904 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 904 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
905 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 905 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 3e4c0414a01a..96eb2a709e21 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -129,7 +129,7 @@ static int misc_open(struct inode * inode, struct file * file) | |||
129 | int minor = iminor(inode); | 129 | int minor = iminor(inode); |
130 | struct miscdevice *c; | 130 | struct miscdevice *c; |
131 | int err = -ENODEV; | 131 | int err = -ENODEV; |
132 | struct file_operations *old_fops, *new_fops = NULL; | 132 | const struct file_operations *old_fops, *new_fops = NULL; |
133 | 133 | ||
134 | down(&misc_sem); | 134 | down(&misc_sem); |
135 | 135 | ||
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index e7fd0b08e0b7..7e188a4d602a 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h | |||
@@ -118,7 +118,7 @@ | |||
118 | 118 | ||
119 | // enable CTS interrupt | 119 | // enable CTS interrupt |
120 | #define MOXA_MUST_IER_ECTSI 0x80 | 120 | #define MOXA_MUST_IER_ECTSI 0x80 |
121 | // eanble RTS interrupt | 121 | // enable RTS interrupt |
122 | #define MOXA_MUST_IER_ERTSI 0x40 | 122 | #define MOXA_MUST_IER_ERTSI 0x40 |
123 | // enable Xon/Xoff interrupt | 123 | // enable Xon/Xoff interrupt |
124 | #define MOXA_MUST_IER_XINT 0x20 | 124 | #define MOXA_MUST_IER_XINT 0x20 |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d68be61f0a49..fee2aca3f6a5 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -941,17 +941,6 @@ static void* mgsl_get_text_ptr(void) | |||
941 | return mgsl_get_text_ptr; | 941 | return mgsl_get_text_ptr; |
942 | } | 942 | } |
943 | 943 | ||
944 | /* | ||
945 | * tmp_buf is used as a temporary buffer by mgsl_write. We need to | ||
946 | * lock it in case the COPY_FROM_USER blocks while swapping in a page, | ||
947 | * and some other program tries to do a serial write at the same time. | ||
948 | * Since the lock will only come under contention when the system is | ||
949 | * swapping and available memory is low, it makes sense to share one | ||
950 | * buffer across all the serial ioports, since it significantly saves | ||
951 | * memory if large numbers of serial ports are open. | ||
952 | */ | ||
953 | static unsigned char *tmp_buf; | ||
954 | |||
955 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, | 944 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, |
956 | char *name, const char *routine) | 945 | char *name, const char *routine) |
957 | { | 946 | { |
@@ -2150,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty, | |||
2150 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) | 2139 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) |
2151 | goto cleanup; | 2140 | goto cleanup; |
2152 | 2141 | ||
2153 | if (!tty || !info->xmit_buf || !tmp_buf) | 2142 | if (!tty || !info->xmit_buf) |
2154 | goto cleanup; | 2143 | goto cleanup; |
2155 | 2144 | ||
2156 | if ( info->params.mode == MGSL_MODE_HDLC || | 2145 | if ( info->params.mode == MGSL_MODE_HDLC || |
@@ -3438,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) | |||
3438 | { | 3427 | { |
3439 | struct mgsl_struct *info; | 3428 | struct mgsl_struct *info; |
3440 | int retval, line; | 3429 | int retval, line; |
3441 | unsigned long page; | ||
3442 | unsigned long flags; | 3430 | unsigned long flags; |
3443 | 3431 | ||
3444 | /* verify range of specified line number */ | 3432 | /* verify range of specified line number */ |
@@ -3472,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) | |||
3472 | goto cleanup; | 3460 | goto cleanup; |
3473 | } | 3461 | } |
3474 | 3462 | ||
3475 | if (!tmp_buf) { | ||
3476 | page = get_zeroed_page(GFP_KERNEL); | ||
3477 | if (!page) { | ||
3478 | retval = -ENOMEM; | ||
3479 | goto cleanup; | ||
3480 | } | ||
3481 | if (tmp_buf) | ||
3482 | free_page(page); | ||
3483 | else | ||
3484 | tmp_buf = (unsigned char *) page; | ||
3485 | } | ||
3486 | |||
3487 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 3463 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
3488 | 3464 | ||
3489 | spin_lock_irqsave(&info->netlock, flags); | 3465 | spin_lock_irqsave(&info->netlock, flags); |
@@ -4502,11 +4478,6 @@ static void synclink_cleanup(void) | |||
4502 | kfree(tmp); | 4478 | kfree(tmp); |
4503 | } | 4479 | } |
4504 | 4480 | ||
4505 | if (tmp_buf) { | ||
4506 | free_page((unsigned long) tmp_buf); | ||
4507 | tmp_buf = NULL; | ||
4508 | } | ||
4509 | |||
4510 | if (pci_registered) | 4481 | if (pci_registered) |
4511 | pci_unregister_driver(&synclink_pci_driver); | 4482 | pci_unregister_driver(&synclink_pci_driver); |
4512 | } | 4483 | } |
@@ -6025,7 +5996,7 @@ static void usc_set_async_mode( struct mgsl_struct *info ) | |||
6025 | * <15..8> ? RxFIFO IRQ Request Level | 5996 | * <15..8> ? RxFIFO IRQ Request Level |
6026 | * | 5997 | * |
6027 | * Note: For async mode the receive FIFO level must be set | 5998 | * Note: For async mode the receive FIFO level must be set |
6028 | * to 0 to aviod the situation where the FIFO contains fewer bytes | 5999 | * to 0 to avoid the situation where the FIFO contains fewer bytes |
6029 | * than the trigger level and no more data is expected. | 6000 | * than the trigger level and no more data is expected. |
6030 | * | 6001 | * |
6031 | * <7> 0 Exited Hunt IA (Interrupt Arm) | 6002 | * <7> 0 Exited Hunt IA (Interrupt Arm) |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 738ec2f4e563..b4d1f4eea435 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $ | 2 | * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $ |
3 | * | 3 | * |
4 | * Device driver for Microgate SyncLink GT serial adapters. | 4 | * Device driver for Microgate SyncLink GT serial adapters. |
5 | * | 5 | * |
@@ -92,7 +92,7 @@ | |||
92 | * module identification | 92 | * module identification |
93 | */ | 93 | */ |
94 | static char *driver_name = "SyncLink GT"; | 94 | static char *driver_name = "SyncLink GT"; |
95 | static char *driver_version = "$Revision: 4.22 $"; | 95 | static char *driver_version = "$Revision: 4.25 $"; |
96 | static char *tty_driver_name = "synclink_gt"; | 96 | static char *tty_driver_name = "synclink_gt"; |
97 | static char *tty_dev_prefix = "ttySLG"; | 97 | static char *tty_dev_prefix = "ttySLG"; |
98 | MODULE_LICENSE("GPL"); | 98 | MODULE_LICENSE("GPL"); |
@@ -188,6 +188,20 @@ static void hdlcdev_exit(struct slgt_info *info); | |||
188 | #define SLGT_REG_SIZE 256 | 188 | #define SLGT_REG_SIZE 256 |
189 | 189 | ||
190 | /* | 190 | /* |
191 | * conditional wait facility | ||
192 | */ | ||
193 | struct cond_wait { | ||
194 | struct cond_wait *next; | ||
195 | wait_queue_head_t q; | ||
196 | wait_queue_t wait; | ||
197 | unsigned int data; | ||
198 | }; | ||
199 | static void init_cond_wait(struct cond_wait *w, unsigned int data); | ||
200 | static void add_cond_wait(struct cond_wait **head, struct cond_wait *w); | ||
201 | static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w); | ||
202 | static void flush_cond_wait(struct cond_wait **head); | ||
203 | |||
204 | /* | ||
191 | * DMA buffer descriptor and access macros | 205 | * DMA buffer descriptor and access macros |
192 | */ | 206 | */ |
193 | struct slgt_desc | 207 | struct slgt_desc |
@@ -269,6 +283,9 @@ struct slgt_info { | |||
269 | struct timer_list tx_timer; | 283 | struct timer_list tx_timer; |
270 | struct timer_list rx_timer; | 284 | struct timer_list rx_timer; |
271 | 285 | ||
286 | unsigned int gpio_present; | ||
287 | struct cond_wait *gpio_wait_q; | ||
288 | |||
272 | spinlock_t lock; /* spinlock for synchronizing with ISR */ | 289 | spinlock_t lock; /* spinlock for synchronizing with ISR */ |
273 | 290 | ||
274 | struct work_struct task; | 291 | struct work_struct task; |
@@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = { | |||
379 | #define MASK_OVERRUN BIT4 | 396 | #define MASK_OVERRUN BIT4 |
380 | 397 | ||
381 | #define GSR 0x00 /* global status */ | 398 | #define GSR 0x00 /* global status */ |
399 | #define JCR 0x04 /* JTAG control */ | ||
400 | #define IODR 0x08 /* GPIO direction */ | ||
401 | #define IOER 0x0c /* GPIO interrupt enable */ | ||
402 | #define IOVR 0x10 /* GPIO value */ | ||
403 | #define IOSR 0x14 /* GPIO interrupt status */ | ||
382 | #define TDR 0x80 /* tx data */ | 404 | #define TDR 0x80 /* tx data */ |
383 | #define RDR 0x80 /* rx data */ | 405 | #define RDR 0x80 /* rx data */ |
384 | #define TCR 0x82 /* tx control */ | 406 | #define TCR 0x82 /* tx control */ |
@@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
503 | static void set_break(struct tty_struct *tty, int break_state); | 525 | static void set_break(struct tty_struct *tty, int break_state); |
504 | static int get_interface(struct slgt_info *info, int __user *if_mode); | 526 | static int get_interface(struct slgt_info *info, int __user *if_mode); |
505 | static int set_interface(struct slgt_info *info, int if_mode); | 527 | static int set_interface(struct slgt_info *info, int if_mode); |
528 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
529 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
530 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
506 | 531 | ||
507 | /* | 532 | /* |
508 | * driver functions | 533 | * driver functions |
@@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1112 | return get_interface(info, argp); | 1137 | return get_interface(info, argp); |
1113 | case MGSL_IOCSIF: | 1138 | case MGSL_IOCSIF: |
1114 | return set_interface(info,(int)arg); | 1139 | return set_interface(info,(int)arg); |
1140 | case MGSL_IOCSGPIO: | ||
1141 | return set_gpio(info, argp); | ||
1142 | case MGSL_IOCGGPIO: | ||
1143 | return get_gpio(info, argp); | ||
1144 | case MGSL_IOCWAITGPIO: | ||
1145 | return wait_gpio(info, argp); | ||
1115 | case TIOCGICOUNT: | 1146 | case TIOCGICOUNT: |
1116 | spin_lock_irqsave(&info->lock,flags); | 1147 | spin_lock_irqsave(&info->lock,flags); |
1117 | cnow = info->icount; | 1148 | cnow = info->icount; |
@@ -1762,10 +1793,6 @@ static void rx_async(struct slgt_info *info) | |||
1762 | DBGDATA(info, p, count, "rx"); | 1793 | DBGDATA(info, p, count, "rx"); |
1763 | 1794 | ||
1764 | for(i=0 ; i < count; i+=2, p+=2) { | 1795 | for(i=0 ; i < count; i+=2, p+=2) { |
1765 | if (tty && chars) { | ||
1766 | tty_flip_buffer_push(tty); | ||
1767 | chars = 0; | ||
1768 | } | ||
1769 | ch = *p; | 1796 | ch = *p; |
1770 | icount->rx++; | 1797 | icount->rx++; |
1771 | 1798 | ||
@@ -2158,6 +2185,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) | |||
2158 | } | 2185 | } |
2159 | } | 2186 | } |
2160 | 2187 | ||
2188 | static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state) | ||
2189 | { | ||
2190 | struct cond_wait *w, *prev; | ||
2191 | |||
2192 | /* wake processes waiting for specific transitions */ | ||
2193 | for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) { | ||
2194 | if (w->data & changed) { | ||
2195 | w->data = state; | ||
2196 | wake_up_interruptible(&w->q); | ||
2197 | if (prev != NULL) | ||
2198 | prev->next = w->next; | ||
2199 | else | ||
2200 | info->gpio_wait_q = w->next; | ||
2201 | } else | ||
2202 | prev = w; | ||
2203 | } | ||
2204 | } | ||
2205 | |||
2161 | /* interrupt service routine | 2206 | /* interrupt service routine |
2162 | * | 2207 | * |
2163 | * irq interrupt number | 2208 | * irq interrupt number |
@@ -2193,6 +2238,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
2193 | } | 2238 | } |
2194 | } | 2239 | } |
2195 | 2240 | ||
2241 | if (info->gpio_present) { | ||
2242 | unsigned int state; | ||
2243 | unsigned int changed; | ||
2244 | while ((changed = rd_reg32(info, IOSR)) != 0) { | ||
2245 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); | ||
2246 | /* read latched state of GPIO signals */ | ||
2247 | state = rd_reg32(info, IOVR); | ||
2248 | /* clear pending GPIO interrupt bits */ | ||
2249 | wr_reg32(info, IOSR, changed); | ||
2250 | for (i=0 ; i < info->port_count ; i++) { | ||
2251 | if (info->port_array[i] != NULL) | ||
2252 | isr_gpio(info->port_array[i], changed, state); | ||
2253 | } | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2196 | for(i=0; i < info->port_count ; i++) { | 2257 | for(i=0; i < info->port_count ; i++) { |
2197 | struct slgt_info *port = info->port_array[i]; | 2258 | struct slgt_info *port = info->port_array[i]; |
2198 | 2259 | ||
@@ -2276,6 +2337,8 @@ static void shutdown(struct slgt_info *info) | |||
2276 | set_signals(info); | 2337 | set_signals(info); |
2277 | } | 2338 | } |
2278 | 2339 | ||
2340 | flush_cond_wait(&info->gpio_wait_q); | ||
2341 | |||
2279 | spin_unlock_irqrestore(&info->lock,flags); | 2342 | spin_unlock_irqrestore(&info->lock,flags); |
2280 | 2343 | ||
2281 | if (info->tty) | 2344 | if (info->tty) |
@@ -2650,6 +2713,175 @@ static int set_interface(struct slgt_info *info, int if_mode) | |||
2650 | return 0; | 2713 | return 0; |
2651 | } | 2714 | } |
2652 | 2715 | ||
2716 | /* | ||
2717 | * set general purpose IO pin state and direction | ||
2718 | * | ||
2719 | * user_gpio fields: | ||
2720 | * state each bit indicates a pin state | ||
2721 | * smask set bit indicates pin state to set | ||
2722 | * dir each bit indicates a pin direction (0=input, 1=output) | ||
2723 | * dmask set bit indicates pin direction to set | ||
2724 | */ | ||
2725 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
2726 | { | ||
2727 | unsigned long flags; | ||
2728 | struct gpio_desc gpio; | ||
2729 | __u32 data; | ||
2730 | |||
2731 | if (!info->gpio_present) | ||
2732 | return -EINVAL; | ||
2733 | if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) | ||
2734 | return -EFAULT; | ||
2735 | DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n", | ||
2736 | info->device_name, gpio.state, gpio.smask, | ||
2737 | gpio.dir, gpio.dmask)); | ||
2738 | |||
2739 | spin_lock_irqsave(&info->lock,flags); | ||
2740 | if (gpio.dmask) { | ||
2741 | data = rd_reg32(info, IODR); | ||
2742 | data |= gpio.dmask & gpio.dir; | ||
2743 | data &= ~(gpio.dmask & ~gpio.dir); | ||
2744 | wr_reg32(info, IODR, data); | ||
2745 | } | ||
2746 | if (gpio.smask) { | ||
2747 | data = rd_reg32(info, IOVR); | ||
2748 | data |= gpio.smask & gpio.state; | ||
2749 | data &= ~(gpio.smask & ~gpio.state); | ||
2750 | wr_reg32(info, IOVR, data); | ||
2751 | } | ||
2752 | spin_unlock_irqrestore(&info->lock,flags); | ||
2753 | |||
2754 | return 0; | ||
2755 | } | ||
2756 | |||
2757 | /* | ||
2758 | * get general purpose IO pin state and direction | ||
2759 | */ | ||
2760 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
2761 | { | ||
2762 | struct gpio_desc gpio; | ||
2763 | if (!info->gpio_present) | ||
2764 | return -EINVAL; | ||
2765 | gpio.state = rd_reg32(info, IOVR); | ||
2766 | gpio.smask = 0xffffffff; | ||
2767 | gpio.dir = rd_reg32(info, IODR); | ||
2768 | gpio.dmask = 0xffffffff; | ||
2769 | if (copy_to_user(user_gpio, &gpio, sizeof(gpio))) | ||
2770 | return -EFAULT; | ||
2771 | DBGINFO(("%s get_gpio state=%08x dir=%08x\n", | ||
2772 | info->device_name, gpio.state, gpio.dir)); | ||
2773 | return 0; | ||
2774 | } | ||
2775 | |||
2776 | /* | ||
2777 | * conditional wait facility | ||
2778 | */ | ||
2779 | static void init_cond_wait(struct cond_wait *w, unsigned int data) | ||
2780 | { | ||
2781 | init_waitqueue_head(&w->q); | ||
2782 | init_waitqueue_entry(&w->wait, current); | ||
2783 | w->data = data; | ||
2784 | } | ||
2785 | |||
2786 | static void add_cond_wait(struct cond_wait **head, struct cond_wait *w) | ||
2787 | { | ||
2788 | set_current_state(TASK_INTERRUPTIBLE); | ||
2789 | add_wait_queue(&w->q, &w->wait); | ||
2790 | w->next = *head; | ||
2791 | *head = w; | ||
2792 | } | ||
2793 | |||
2794 | static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw) | ||
2795 | { | ||
2796 | struct cond_wait *w, *prev; | ||
2797 | remove_wait_queue(&cw->q, &cw->wait); | ||
2798 | set_current_state(TASK_RUNNING); | ||
2799 | for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) { | ||
2800 | if (w == cw) { | ||
2801 | if (prev != NULL) | ||
2802 | prev->next = w->next; | ||
2803 | else | ||
2804 | *head = w->next; | ||
2805 | break; | ||
2806 | } | ||
2807 | } | ||
2808 | } | ||
2809 | |||
2810 | static void flush_cond_wait(struct cond_wait **head) | ||
2811 | { | ||
2812 | while (*head != NULL) { | ||
2813 | wake_up_interruptible(&(*head)->q); | ||
2814 | *head = (*head)->next; | ||
2815 | } | ||
2816 | } | ||
2817 | |||
2818 | /* | ||
2819 | * wait for general purpose I/O pin(s) to enter specified state | ||
2820 | * | ||
2821 | * user_gpio fields: | ||
2822 | * state - bit indicates target pin state | ||
2823 | * smask - set bit indicates watched pin | ||
2824 | * | ||
2825 | * The wait ends when at least one watched pin enters the specified | ||
2826 | * state. When 0 (no error) is returned, user_gpio->state is set to the | ||
2827 | * state of all GPIO pins when the wait ends. | ||
2828 | * | ||
2829 | * Note: Each pin may be a dedicated input, dedicated output, or | ||
2830 | * configurable input/output. The number and configuration of pins | ||
2831 | * varies with the specific adapter model. Only input pins (dedicated | ||
2832 | * or configured) can be monitored with this function. | ||
2833 | */ | ||
2834 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
2835 | { | ||
2836 | unsigned long flags; | ||
2837 | int rc = 0; | ||
2838 | struct gpio_desc gpio; | ||
2839 | struct cond_wait wait; | ||
2840 | u32 state; | ||
2841 | |||
2842 | if (!info->gpio_present) | ||
2843 | return -EINVAL; | ||
2844 | if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) | ||
2845 | return -EFAULT; | ||
2846 | DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n", | ||
2847 | info->device_name, gpio.state, gpio.smask)); | ||
2848 | /* ignore output pins identified by set IODR bit */ | ||
2849 | if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0) | ||
2850 | return -EINVAL; | ||
2851 | init_cond_wait(&wait, gpio.smask); | ||
2852 | |||
2853 | spin_lock_irqsave(&info->lock, flags); | ||
2854 | /* enable interrupts for watched pins */ | ||
2855 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); | ||
2856 | /* get current pin states */ | ||
2857 | state = rd_reg32(info, IOVR); | ||
2858 | |||
2859 | if (gpio.smask & ~(state ^ gpio.state)) { | ||
2860 | /* already in target state */ | ||
2861 | gpio.state = state; | ||
2862 | } else { | ||
2863 | /* wait for target state */ | ||
2864 | add_cond_wait(&info->gpio_wait_q, &wait); | ||
2865 | spin_unlock_irqrestore(&info->lock, flags); | ||
2866 | schedule(); | ||
2867 | if (signal_pending(current)) | ||
2868 | rc = -ERESTARTSYS; | ||
2869 | else | ||
2870 | gpio.state = wait.data; | ||
2871 | spin_lock_irqsave(&info->lock, flags); | ||
2872 | remove_cond_wait(&info->gpio_wait_q, &wait); | ||
2873 | } | ||
2874 | |||
2875 | /* disable all GPIO interrupts if no waiting processes */ | ||
2876 | if (info->gpio_wait_q == NULL) | ||
2877 | wr_reg32(info, IOER, 0); | ||
2878 | spin_unlock_irqrestore(&info->lock,flags); | ||
2879 | |||
2880 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) | ||
2881 | rc = -EFAULT; | ||
2882 | return rc; | ||
2883 | } | ||
2884 | |||
2653 | static int modem_input_wait(struct slgt_info *info,int arg) | 2885 | static int modem_input_wait(struct slgt_info *info,int arg) |
2654 | { | 2886 | { |
2655 | unsigned long flags; | 2887 | unsigned long flags; |
@@ -3166,8 +3398,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
3166 | } else { | 3398 | } else { |
3167 | port_array[0]->irq_requested = 1; | 3399 | port_array[0]->irq_requested = 1; |
3168 | adapter_test(port_array[0]); | 3400 | adapter_test(port_array[0]); |
3169 | for (i=1 ; i < port_count ; i++) | 3401 | for (i=1 ; i < port_count ; i++) { |
3170 | port_array[i]->init_error = port_array[0]->init_error; | 3402 | port_array[i]->init_error = port_array[0]->init_error; |
3403 | port_array[i]->gpio_present = port_array[0]->gpio_present; | ||
3404 | } | ||
3171 | } | 3405 | } |
3172 | } | 3406 | } |
3173 | } | 3407 | } |
@@ -4301,7 +4535,7 @@ static int register_test(struct slgt_info *info) | |||
4301 | break; | 4535 | break; |
4302 | } | 4536 | } |
4303 | } | 4537 | } |
4304 | 4538 | info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0; | |
4305 | info->init_error = rc ? 0 : DiagStatus_AddressFailure; | 4539 | info->init_error = rc ? 0 : DiagStatus_AddressFailure; |
4306 | return rc; | 4540 | return rc; |
4307 | } | 4541 | } |