aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/ans-lcd.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-10-10 07:38:57 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-10-14 11:36:50 -0400
commit95fdac73725c15072d068ac7f131958cf5c324e4 (patch)
tree3e76d637ca4762fdaad107c829eb2b9545da3717 /drivers/macintosh/ans-lcd.c
parent9e8ab74ddaa591575f599248080a1f0d917a56ee (diff)
macintosh: Remove BKL from ans-lcd
The ans-lcd driver got the cycle_kernel_lock() in anslcd_open() from the BKL pushdown and it still uses the locked ioctl. The BKL serialization in this driver is more than obscure and definitely does not cover all possible corner cases. Protect the access to the hardware with a local mutex and get rid of BKL and locked ioctl. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> LKML-Reference: <20091010153349.966159859@linutronix.de> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/macintosh/ans-lcd.c')
-rw-r--r--drivers/macintosh/ans-lcd.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 6a8221893256..a3d25da2f275 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -3,7 +3,6 @@
3 */ 3 */
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/smp_lock.h>
7#include <linux/errno.h> 6#include <linux/errno.h>
8#include <linux/kernel.h> 7#include <linux/kernel.h>
9#include <linux/miscdevice.h> 8#include <linux/miscdevice.h>
@@ -26,6 +25,7 @@
26static unsigned long anslcd_short_delay = 80; 25static unsigned long anslcd_short_delay = 80;
27static unsigned long anslcd_long_delay = 3280; 26static unsigned long anslcd_long_delay = 3280;
28static volatile unsigned char __iomem *anslcd_ptr; 27static volatile unsigned char __iomem *anslcd_ptr;
28static DEFINE_MUTEX(anslcd_mutex);
29 29
30#undef DEBUG 30#undef DEBUG
31 31
@@ -65,26 +65,31 @@ anslcd_write( struct file * file, const char __user * buf,
65 65
66 if (!access_ok(VERIFY_READ, buf, count)) 66 if (!access_ok(VERIFY_READ, buf, count))
67 return -EFAULT; 67 return -EFAULT;
68
69 mutex_lock(&anslcd_mutex);
68 for ( i = *ppos; count > 0; ++i, ++p, --count ) 70 for ( i = *ppos; count > 0; ++i, ++p, --count )
69 { 71 {
70 char c; 72 char c;
71 __get_user(c, p); 73 __get_user(c, p);
72 anslcd_write_byte_data( c ); 74 anslcd_write_byte_data( c );
73 } 75 }
76 mutex_unlock(&anslcd_mutex);
74 *ppos = i; 77 *ppos = i;
75 return p - buf; 78 return p - buf;
76} 79}
77 80
78static int 81static long
79anslcd_ioctl( struct inode * inode, struct file * file, 82anslcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
80 unsigned int cmd, unsigned long arg )
81{ 83{
82 char ch, __user *temp; 84 char ch, __user *temp;
85 long ret = 0;
83 86
84#ifdef DEBUG 87#ifdef DEBUG
85 printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg); 88 printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg);
86#endif 89#endif
87 90
91 mutex_lock(&anslcd_mutex);
92
88 switch ( cmd ) 93 switch ( cmd )
89 { 94 {
90 case ANSLCD_CLEAR: 95 case ANSLCD_CLEAR:
@@ -93,7 +98,7 @@ anslcd_ioctl( struct inode * inode, struct file * file,
93 anslcd_write_byte_ctrl ( 0x06 ); 98 anslcd_write_byte_ctrl ( 0x06 );
94 anslcd_write_byte_ctrl ( 0x01 ); 99 anslcd_write_byte_ctrl ( 0x01 );
95 anslcd_write_byte_ctrl ( 0x02 ); 100 anslcd_write_byte_ctrl ( 0x02 );
96 return 0; 101 break;
97 case ANSLCD_SENDCTRL: 102 case ANSLCD_SENDCTRL:
98 temp = (char __user *) arg; 103 temp = (char __user *) arg;
99 __get_user(ch, temp); 104 __get_user(ch, temp);
@@ -101,33 +106,37 @@ anslcd_ioctl( struct inode * inode, struct file * file,
101 anslcd_write_byte_ctrl ( ch ); 106 anslcd_write_byte_ctrl ( ch );
102 __get_user(ch, temp); 107 __get_user(ch, temp);
103 } 108 }
104 return 0; 109 break;
105 case ANSLCD_SETSHORTDELAY: 110 case ANSLCD_SETSHORTDELAY:
106 if (!capable(CAP_SYS_ADMIN)) 111 if (!capable(CAP_SYS_ADMIN))
107 return -EACCES; 112 ret =-EACCES;
108 anslcd_short_delay=arg; 113 else
109 return 0; 114 anslcd_short_delay=arg;
115 break;
110 case ANSLCD_SETLONGDELAY: 116 case ANSLCD_SETLONGDELAY:
111 if (!capable(CAP_SYS_ADMIN)) 117 if (!capable(CAP_SYS_ADMIN))
112 return -EACCES; 118 ret = -EACCES;
113 anslcd_long_delay=arg; 119 else
114 return 0; 120 anslcd_long_delay=arg;
121 break;
115 default: 122 default:
116 return -EINVAL; 123 ret = -EINVAL;
117 } 124 }
125
126 mutex_unlock(&anslcd_mutex);
127 return ret;
118} 128}
119 129
120static int 130static int
121anslcd_open( struct inode * inode, struct file * file ) 131anslcd_open( struct inode * inode, struct file * file )
122{ 132{
123 cycle_kernel_lock();
124 return 0; 133 return 0;
125} 134}
126 135
127const struct file_operations anslcd_fops = { 136const struct file_operations anslcd_fops = {
128 .write = anslcd_write, 137 .write = anslcd_write,
129 .ioctl = anslcd_ioctl, 138 .unlocked_ioctl = anslcd_ioctl,
130 .open = anslcd_open, 139 .open = anslcd_open,
131}; 140};
132 141
133static struct miscdevice anslcd_dev = { 142static struct miscdevice anslcd_dev = {
@@ -168,6 +177,7 @@ anslcd_init(void)
168 printk(KERN_DEBUG "LCD: init\n"); 177 printk(KERN_DEBUG "LCD: init\n");
169#endif 178#endif
170 179
180 mutex_lock(&anslcd_mutex);
171 anslcd_write_byte_ctrl ( 0x38 ); 181 anslcd_write_byte_ctrl ( 0x38 );
172 anslcd_write_byte_ctrl ( 0x0c ); 182 anslcd_write_byte_ctrl ( 0x0c );
173 anslcd_write_byte_ctrl ( 0x06 ); 183 anslcd_write_byte_ctrl ( 0x06 );
@@ -176,6 +186,7 @@ anslcd_init(void)
176 for(a=0;a<80;a++) { 186 for(a=0;a<80;a++) {
177 anslcd_write_byte_data(anslcd_logo[a]); 187 anslcd_write_byte_data(anslcd_logo[a]);
178 } 188 }
189 mutex_unlock(&anslcd_mutex);
179 return 0; 190 return 0;
180} 191}
181 192