Skip to content

Commit

Permalink
macintosh: Remove BKL from ans-lcd
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Thomas Gleixner committed Oct 14, 2009
1 parent 9e8ab74 commit 95fdac7
Showing 1 changed file with 28 additions and 17 deletions.
45 changes: 28 additions & 17 deletions drivers/macintosh/ans-lcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/

#include <linux/types.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
Expand All @@ -26,6 +25,7 @@
static unsigned long anslcd_short_delay = 80;
static unsigned long anslcd_long_delay = 3280;
static volatile unsigned char __iomem *anslcd_ptr;
static DEFINE_MUTEX(anslcd_mutex);

#undef DEBUG

Expand Down Expand Up @@ -65,26 +65,31 @@ anslcd_write( struct file * file, const char __user * buf,

if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;

mutex_lock(&anslcd_mutex);
for ( i = *ppos; count > 0; ++i, ++p, --count )
{
char c;
__get_user(c, p);
anslcd_write_byte_data( c );
}
mutex_unlock(&anslcd_mutex);
*ppos = i;
return p - buf;
}

static int
anslcd_ioctl( struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg )
static long
anslcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
char ch, __user *temp;
long ret = 0;

#ifdef DEBUG
printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg);
#endif

mutex_lock(&anslcd_mutex);

switch ( cmd )
{
case ANSLCD_CLEAR:
Expand All @@ -93,41 +98,45 @@ anslcd_ioctl( struct inode * inode, struct file * file,
anslcd_write_byte_ctrl ( 0x06 );
anslcd_write_byte_ctrl ( 0x01 );
anslcd_write_byte_ctrl ( 0x02 );
return 0;
break;
case ANSLCD_SENDCTRL:
temp = (char __user *) arg;
__get_user(ch, temp);
for (; ch; temp++) { /* FIXME: This is ugly, but should work, as a \0 byte is not a valid command code */
anslcd_write_byte_ctrl ( ch );
__get_user(ch, temp);
}
return 0;
break;
case ANSLCD_SETSHORTDELAY:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
anslcd_short_delay=arg;
return 0;
ret =-EACCES;
else
anslcd_short_delay=arg;
break;
case ANSLCD_SETLONGDELAY:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
anslcd_long_delay=arg;
return 0;
ret = -EACCES;
else
anslcd_long_delay=arg;
break;
default:
return -EINVAL;
ret = -EINVAL;
}

mutex_unlock(&anslcd_mutex);
return ret;
}

static int
anslcd_open( struct inode * inode, struct file * file )
{
cycle_kernel_lock();
return 0;
}

const struct file_operations anslcd_fops = {
.write = anslcd_write,
.ioctl = anslcd_ioctl,
.open = anslcd_open,
.write = anslcd_write,
.unlocked_ioctl = anslcd_ioctl,
.open = anslcd_open,
};

static struct miscdevice anslcd_dev = {
Expand Down Expand Up @@ -168,6 +177,7 @@ anslcd_init(void)
printk(KERN_DEBUG "LCD: init\n");
#endif

mutex_lock(&anslcd_mutex);
anslcd_write_byte_ctrl ( 0x38 );
anslcd_write_byte_ctrl ( 0x0c );
anslcd_write_byte_ctrl ( 0x06 );
Expand All @@ -176,6 +186,7 @@ anslcd_init(void)
for(a=0;a<80;a++) {
anslcd_write_byte_data(anslcd_logo[a]);
}
mutex_unlock(&anslcd_mutex);
return 0;
}

Expand Down

0 comments on commit 95fdac7

Please sign in to comment.