lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20060926120821.e11f3254.akpm@osdl.org>
Date:	Tue, 26 Sep 2006 12:08:21 -0700
From:	Andrew Morton <akpm@...l.org>
To:	Miguel Ojeda Sandonis <maxextreme@...il.com>
Cc:	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2.6.18 real-V5] drivers: add lcd display support

On Fri, 22 Sep 2006 22:03:46 +0200
Miguel Ojeda Sandonis <maxextreme@...il.com> wrote:

> miguelojeda-2.6.18-add-lcd-display-support.patch
> 
> ...
>
> diff -uprN -X dontdiff linux-2.6.18-vanilla/include/linux/device.h linux-2.6.18/include/linux/device.h
> --- linux-2.6.18-vanilla/include/linux/device.h	2006-09-20 14:52:00.000000000 +0200
> +++ linux-2.6.18/include/linux/device.h	2006-09-20 14:55:56.000000000 +0200
> @@ -271,7 +271,7 @@ struct class_interface {
>  extern int class_interface_register(struct class_interface *);
>  extern void class_interface_unregister(struct class_interface *);
>  
> -extern struct class *class_create(struct module *owner, char *name);
> +extern struct class *class_create(struct module *owner, const char *name);

Please prepare a separate patch for this, send to Greg.

> --- linux-2.6.18-vanilla/drivers/lcddisplay/cfag12864b.c	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.18/drivers/lcddisplay/cfag12864b.c	2006-09-22 21:46:52.000000000 +0200
> @@ -0,0 +1,529 @@
> +/*
> + *    Filename: cfag12864b.c
> + *     Version: 0.1.0
> + * Description: cfag12864b LCD Display Driver
> + *     License: GPLv2
> + *     Depends: lcddisplay ks0108
> + *
> + *      Author: Miguel Ojeda Sandonis <maxextreme@...il.com>
> + *        Date: 2006-09-21
> + */
> +
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/fs.h>
> +#include <linux/cdev.h>
> +#include <linux/device.h>
> +#include <linux/lcddisplay.h>
> +#include <linux/ks0108.h>
> +#include <linux/cfag12864b.h>
> +#include <asm/uaccess.h>
> +
> +#define NAME "cfag12864b"
> +#define PRINTK_PREFIX  KERN_INFO NAME ": "

In numerous places the driver uses PRINTK_PREFIX for reporting errors.  It
should use KERN_ERR.  I suggest that PRINTK_PREFIX be removed and that you
open-code all the printk facility levels, make sure that the appropriate
level is being used at each site.

> +
> +
> +/*
> + * Device
> + */
> +
> +static const unsigned int cfag12864b_firstminor;
> +static const unsigned int cfag12864b_ndevices = 1;
> +static const char * cfag12864b_name = NAME;

The more usual kernel style is to not put a space after the `*':

	static const char *cfag12864b_name = NAME;

(this affects the entire patch).


Suggest that cfag12864b_name be removed - just use NAME at the single place
where this variable is used.

> +static int cfag12864b_major;
> +static int cfag12864b_minor;
> +static dev_t cfag12864b_device;
> +struct cdev cfag12864b_chardevice;
> +
> +
> +
> +

One blank line is sufficient (there are many instances of this)

> +/*
> + * cfag12864b Commands
> + */
> +
> +static const unsigned int cfag12864b_bits = 8;
> +static const unsigned int cfag12864b_width = CFAG12864B_WIDTH;
> +static const unsigned int cfag12864b_height = CFAG12864B_HEIGHT;
> +static const unsigned int cfag12864b_matrixsize = CFAG12864B_MATRIXSIZE;
> +static const unsigned int cfag12864b_controllers = CFAG12864B_CONTROLLERS;
> +static const unsigned int cfag12864b_pages = CFAG12864B_PAGES;
> +static const unsigned int cfag12864b_addresses = CFAG12864B_ADDRESSES;
> +static const unsigned int cfag12864b_size = CFAG12864B_SIZE;
> +static unsigned char cfag12864b_state;
> +
> +static void cfag12864b_set(void)
> +{
> +	ks0108_writecontrol(cfag12864b_state);
> +}
> +
> +static void cfag12864b_setbit(unsigned char state, unsigned char bit)
> +{
> +	if (state)
> +		set_bit(bit, (void*)&cfag12864b_state);
> +	else
> +		clear_bit(bit, (void*)&cfag12864b_state);
> +	cfag12864b_set();
> +}

bitops are defined on an unsigned long only.  This trick is as ugly as sin
and is buggy on big-endian CPUs.  Suggest that cfag12864b_state be
converted to unsigned long.

> +{
> +	cfag12864b_startline(0);
> +}
> +
> +
> +

blank lines

> +/*
> + * Auxiliary
> + */
> +
> +static void normalizeoffset(unsigned int * offset)

coding style.

> +{
> +	if (*offset >= cfag12864b_pages*cfag12864b_addresses)
> +		*offset -= cfag12864b_pages*cfag12864b_addresses;
> +}

Ths usual kernel style is to put a single space around arithmetic operators
and around comparison operators.  This affects the entire patch, please.


> +void cfag12864b_clear(void)
> +{
> +	unsigned char page,address;
> +
> +	cfag12864b_setcontrollers(1, 1);
> +	for (page=0; page<cfag12864b_pages; ++page) {

For example,

	for (page = 0; page < cfag12864b_pages; page++) {

would be more kernelish.

The use of the identifier `page' here is unfortunate.  We usually expect
such a thing to have type `struct page *'.  I understand that "Each
controller is divided into 8 pages", but it'd be nice if some different
nomenclature could be used here.  If nothing else comes to mind, we can
live with it as-is.

> +void cfag12864b_write(
> +	unsigned short offset,
> +	const unsigned char * buffer,
> +	unsigned short count)
> +{

It is more usual to do

void cfag12864b_write(unsigned short offset, const unsigned char *buffer,
			unsigned short count)
{

> +	for (controller=0; controller < cfag12864b_controllers; ++controller)
> +	for (page=0; page < cfag12864b_pages; ++page)
> +	for (address=0; address < cfag12864b_addresses; ++address) {
> +		dest[(controller*cfag12864b_pages+page)*cfag12864b_addresses+address]=0;
> +		for (bit=0; bit < cfag12864b_bits; ++bit)
> +			if (src[controller*cfag12864b_addresses+address+(page*cfag12864b_bits+bit)*cfag12864b_width])
> +				set_bit(bit, (void*)(dest+(controller*cfag12864b_pages+page)*cfag12864b_addresses+address));
> +	}

That's rather ugly-looking.

It's also probably-incorrect on big-endian CPUs.  Perhaps you should not
use bitops at all for this driver, use open-coded | and &/~ instead?


The driver doesn't have any locking.  Is it racy on SMP and/or
CONFIG_PREEMPT?

> +static int cfag12864b_fopioctlformat(void __user * arg)
> +{
> +	int result;
> +	int ret = -ENOTTY;
> +
> +	unsigned char * tmpbuffer;
> +
> +	tmpbuffer = kmalloc(
> +		sizeof(unsigned char)*cfag12864b_matrixsize,GFP_KERNEL);
> +	if (tmpbuffer == NULL) {
> +		printk(PRINTK_PREFIX "FOP ioctl: ERROR: "
> +			"can't alloc memory %i bytes\n",
> +			sizeof(unsigned char)*cfag12864b_matrixsize);
> +		goto none;
> +	}
> +
> +	result = copy_from_user(
> +		tmpbuffer,
> +		arg,
> +		sizeof(unsigned char)*cfag12864b_matrixsize);

	result = copy_from_user(tmpbuffer, arg, cfag12864b_matrixsize);


> +	if (result != 0) {
> +		printk(PRINTK_PREFIX "FOP ioctl: ERROR: "
> +			"can't copy memory from user\n");
> +		goto bufferalloced;
> +	}
> +	
> +	cfag12864b_format(tmpbuffer);
> +
> +	ret = 0;
> +
> +bufferalloced:
> +	kfree(tmpbuffer);
> +
> +none:
> +	return ret;
> +}
> +
>
> ...
>
> +
> +static struct file_operations cfag12864b_fops =

`static const struct'

> +
> +	class_device_create(
> +		lcddisplay_class,NULL,
> +		cfag12864b_device,
> +		NULL,"cfag12864b%d", cfag12864b_minor);

class_device_create() can fail.

> +void ks0108_writecontrol(unsigned char byte)
> +{
> +	const unsigned int ecycledelay = 2;
> +	udelay(ecycledelay);
> +	parport_write_control(ks0108_parport, byte^(bit(3)|bit(1)|bit(0)));
> +}

udelay(2) would be clearer.

> +void ks0108_displaystate(unsigned char state)
> +{
> +	unsigned char cmd = bit(1) | bit(2) | bit(3) | bit(4) | bit(5);
> +	if (state)
> +		set_bit(0, (void*)&cmd);

argh.  Even if this driver will only ever run on big-endian hardware,
please don't do this.

> +void ks0108_startline(unsigned char startline)
> +{
> +	const unsigned char maxstartline = 63;
> +	unsigned char cmd = bit(6) | bit(7);
> +	if (startline > maxstartline)
> +		startline = maxstartline;

There are a lot of open-coded min() and max() operations in this driver. 
Suggest it be changed to use min() and max().


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ