All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>,
	Andy Whitcroft <apw@shadowen.org>
Cc: Jens Axboe <axboe@kernel.dk>,
	"James E.J. Bottomley" <James.Bottomley@SteelEye.com>,
	linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
	Alessandro Rubini <rubini@vision.unipv.it>,
	linuxppc-dev@ozlabs.org, Paul Mackerras <paulus@samba.org>
Subject: Re: [patch 3/3] ps3: FLASH ROM Storage Driver
Date: Wed, 18 Jul 2007 16:52:22 -0700	[thread overview]
Message-ID: <20070718165222.e504d92e.akpm@linux-foundation.org> (raw)
In-Reply-To: <20070716162206.723142000@pademelon.sonytel.be>

On Mon, 16 Jul 2007 18:15:42 +0200
Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:

> From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> 
> Add a FLASH ROM Storage Driver for the PS3:
>   - Implemented as a misc character device driver
>   - Uses a fixed 256 KiB buffer allocated from boot memory as the hypervisor
>     requires the writing of aligned 256 KiB blocks
> 
> --- /dev/null
> +++ b/drivers/char/ps3flash.c
> @@ -0,0 +1,429 @@
> +/*
> + * PS3 FLASH ROM Storage Driver
> + *
> + * Copyright (C) 2007 Sony Computer Entertainment Inc.
> + * Copyright 2007 Sony Corp.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published
> + * by the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/lv1call.h>
> +#include <asm/ps3stor.h>
> +
> +
> +#define DEVICE_NAME		"ps3flash"
> +
> +#define FLASH_BLOCK_SIZE	(256*1024)
> +
> +
> +struct ps3flash_private {
> +	struct mutex mutex;	/* Bounce buffer mutex */
> +};
> +#define ps3flash_priv(dev)	((dev)->sbd.core.driver_data)

bzzzt!

> +static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	u64 size = dev->regions[dev->region_idx].size*dev->blk_size;
> +
> +	switch (origin) {
> +	case 1:
> +		offset += file->f_pos;
> +		break;
> +	case 2:
> +		offset += size;
> +		break;
> +	}
> +	if (offset < 0)
> +		return -EINVAL;
> +
> +	file->f_pos = offset;
> +	return file->f_pos;
> +}

lseek implementations usually need locking.  file->f_mapping->host->i_mutex
would be typical.

That locking mostly protects 64-bit f_pos on 32-bit architectures so you
can perahps kinda get away with it here.  However the code is a bit racy
even on 64-bit, for silly userspace.

That being said, I'd have thought that you could use one of our many
generic lseek library fucntions here, or even an newly-exported
block_llseek().  That assumes that i_size is correct, which I trust is the
case.

> +static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
> +			     loff_t *pos)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	struct ps3flash_private *priv = ps3flash_priv(dev);
> +	u64 size, start_sector, end_sector, offset;
> +	ssize_t sectors_read;
> +	size_t remaining, n;
> +
> +	dev_dbg(&dev->sbd.core,
> +		"%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
> +		__func__, __LINE__, count, *pos, buf);
> +
> +	size = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (*pos >= size || !count)
> +		return 0;
> +
> +	if (*pos+count > size) {
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u Truncating count from %zu to %llu\n", __func__,
> +			__LINE__, count, size - *pos);
> +		count = size - *pos;
> +	}
> +
> +	start_sector = do_div_llr(*pos, dev->blk_size, &offset);
> +	end_sector = DIV_ROUND_UP(*pos+count, dev->blk_size);
> +
> +	remaining = count;
> +	do {
> +		mutex_lock(&priv->mutex);
> +
> +		sectors_read = ps3flash_read_sectors(dev, start_sector,
> +						     end_sector-start_sector,
> +						     0);
> +		if (sectors_read < 0) {
> +			mutex_unlock(&priv->mutex);
> +			return sectors_read;
> +		}
> +
> +		n = min(remaining, sectors_read*dev->blk_size-offset);
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
> +			__func__, __LINE__, n, dev->bounce_buf+offset, buf);
> +		if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
> +			mutex_unlock(&priv->mutex);
> +			return -EFAULT;
> +		}
> +
> +		mutex_unlock(&priv->mutex);
> +
> +		*pos += n;
> +		buf += n;
> +		remaining -= n;
> +		start_sector += sectors_read;
> +		offset = 0;
> +	} while (remaining > 0);
> +
> +	return count;
> +}

There are several nasty deeply-embedded return points in this function.

> +static ssize_t ps3flash_write(struct file *file, const char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	struct ps3flash_private *priv = ps3flash_priv(dev);
> +	u64 size, chunk_sectors, start_write_sector, end_write_sector,
> +	    end_read_sector, start_read_sector, head, tail, offset;
> +	ssize_t res;
> +	size_t remaining, n;
> +	unsigned int sec_off;
> +
> +	dev_dbg(&dev->sbd.core,
> +		"%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
> +		__func__, __LINE__, count, *pos, buf);
> +
> +	size = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (*pos >= size || !count)
> +		return 0;
> +
> +	if (*pos+count > size) {

checkpatch missed stuff here.

> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u Truncating count from %zu to %llu\n", __func__,
> +			__LINE__, count, size - *pos);
> +		count = size - *pos;
> +	}
> +
> +	chunk_sectors = dev->bounce_size / dev->blk_size;
> +
> +	start_write_sector = do_div_llr(*pos, dev->bounce_size, &offset) *
> +			     chunk_sectors;

It's strange to see a do_div_llr() in the middle of all this 64-bit-only
code.  Could use / and %?

> +	end_write_sector = DIV_ROUND_UP(*pos+count, dev->bounce_size) *
> +			   chunk_sectors;
> +
> +	end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
> +	start_read_sector = (*pos+count) / dev->blk_size;
> +
> +	/*
> +	 * As we have to write in 256 KiB chunks, while we can read in blk_size
> +	 * (usually 512 bytes) chunks, we perform the following steps:
> +	 *   1. Read from start_write_sector to end_read_sector ("head")
> +	 *   2. Read from start_read_sector to end_write_sector ("tail")
> +	 *   3. Copy data to buffer
> +	 *   4. Write from start_write_sector to end_write_sector
> +	 * All of this is complicated by using only one 256 KiB bounce buffer.
> +	 */
> +
> +	head = end_read_sector-start_write_sector;
> +	tail = end_write_sector-start_read_sector;

checkpatch missed this too.

> +	remaining = count;
> +	do {
> +		mutex_lock(&priv->mutex);
> +
> +		if (end_read_sector >= start_read_sector) {
> +			/* Merge head and tail */
> +			dev_dbg(&dev->sbd.core,
> +				"Merged head and tail: %lu sectors at %lu\n",
> +				chunk_sectors, start_write_sector);
> +			res = ps3flash_read_sectors(dev, start_write_sector,
> +						    chunk_sectors, 0);
> +			if (res < 0)
> +				goto fail;
> +		} else {
> +			if (head) {
> +				/* Read head */
> +				dev_dbg(&dev->sbd.core,
> +					"head: %lu sectors at %lu\n", head,
> +					start_write_sector);
> +				res = ps3flash_read_sectors(dev,
> +							    start_write_sector,
> +							    head, 0);
> +				if (res < 0)
> +					goto fail;
> +			}
> +			if (start_read_sector <
> +			    start_write_sector+chunk_sectors) {
> +				/* Read tail */
> +				dev_dbg(&dev->sbd.core,
> +					"tail: %lu sectors at %lu\n", tail,
> +					start_read_sector);
> +				sec_off = start_read_sector-start_write_sector;
> +				res = ps3flash_read_sectors(dev,
> +							    start_read_sector,
> +							    tail, sec_off);
> +				if (res < 0)
> +					goto fail;
> +			}
> +		}
> +
> +		n = min(remaining, dev->bounce_size-offset);
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
> +			__func__, __LINE__, n, buf, dev->bounce_buf+offset);
> +		if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
> +			res = -EFAULT;
> +			goto fail;
> +		}
> +
> +		res = ps3flash_write_chunk(dev, start_write_sector);
> +		if (res < 0)
> +			goto fail;
> +
> +		mutex_unlock(&priv->mutex);
> +
> +		*pos += n;
> +		buf += n;
> +		remaining -= n;
> +		start_write_sector += chunk_sectors;
> +		head = 0;
> +		offset = 0;
> +	} while (remaining > 0);
> +
> +	return count;
> +
> +fail:
> +	mutex_unlock(&priv->mutex);
> +	return res;
> +}
>
> ...
>
> +static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
> +{
> +	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
> +	struct ps3flash_private *priv;
> +	int error;
> +	unsigned long tmp;
> +
> +	tmp = dev->regions[dev->region_idx].start*dev->blk_size;
> +	if (tmp % FLASH_BLOCK_SIZE) {
> +		dev_err(&dev->sbd.core,
> +			"%s:%u region start %lu is not aligned\n", __func__,
> +			__LINE__, tmp);
> +		return -EINVAL;
> +	}
> +	tmp = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (tmp % FLASH_BLOCK_SIZE) {
> +		dev_err(&dev->sbd.core,
> +			"%s:%u region size %lu is not aligned\n", __func__,
> +			__LINE__, tmp);
> +		return -EINVAL;
> +	}
> +
> +	/* use static buffer, kmalloc cannot allocate 256 KiB */
> +	if (!ps3flash_bounce_buffer.address)
> +		return -ENODEV;
> +
> +	if (ps3flash_dev) {
> +		dev_err(&dev->sbd.core,
> +			"Only one FLASH device is supported\n");
> +		return -EBUSY;
> +	}
> +
> +	ps3flash_dev = dev;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		error = -ENOMEM;
> +		goto fail;
> +	}
> +
> +	ps3flash_priv(dev) = priv;
> +	mutex_init(&priv->mutex);
> +
> +	dev->bounce_size = ps3flash_bounce_buffer.size;
> +	dev->bounce_buf = ps3flash_bounce_buffer.address;
> +
> +	error = ps3stor_setup(dev, ps3flash_interrupt);
> +	if (error)
> +		goto fail_free_priv;
> +
> +	ps3flash_misc.parent = &dev->sbd.core;
> +	error = misc_register(&ps3flash_misc);
> +	if (error) {
> +		dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
> +			__func__, __LINE__, error);
> +		goto fail_teardown;
> +	}
> +
> +	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
> +		 __func__, __LINE__, ps3flash_misc.minor);
> +	return 0;
> +
> +fail_teardown:
> +	ps3stor_teardown(dev);
> +fail_free_priv:
> +	kfree(priv);
> +	ps3flash_priv(dev) = NULL;
> +fail:
> +	ps3flash_dev = NULL;
> +	return error;
> +}
> +

WARNING: multiple messages have this Message-ID (diff)
From: Andrew Morton <akpm@linux-foundation.org>
To: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>,
	Andy Whitcroft <apw@shadowen.org>
Cc: Paul Mackerras <paulus@samba.org>, Jens Axboe <axboe@kernel.dk>,
	"James E.J. Bottomley" <James.Bottomley@SteelEye.com>,
	Alessandro Rubini <rubini@vision.unipv.it>,
	linuxppc-dev@ozlabs.org, linux-kernel@vger.kernel.org,
	linux-scsi@vger.kernel.org,
	Geoff Levand <geoffrey.levand@am.sony.com>
Subject: Re: [patch 3/3] ps3: FLASH ROM Storage Driver
Date: Wed, 18 Jul 2007 16:52:22 -0700	[thread overview]
Message-ID: <20070718165222.e504d92e.akpm@linux-foundation.org> (raw)
In-Reply-To: <20070716162206.723142000@pademelon.sonytel.be>

On Mon, 16 Jul 2007 18:15:42 +0200
Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:

> From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> 
> Add a FLASH ROM Storage Driver for the PS3:
>   - Implemented as a misc character device driver
>   - Uses a fixed 256 KiB buffer allocated from boot memory as the hypervisor
>     requires the writing of aligned 256 KiB blocks
> 
> --- /dev/null
> +++ b/drivers/char/ps3flash.c
> @@ -0,0 +1,429 @@
> +/*
> + * PS3 FLASH ROM Storage Driver
> + *
> + * Copyright (C) 2007 Sony Computer Entertainment Inc.
> + * Copyright 2007 Sony Corp.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published
> + * by the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/lv1call.h>
> +#include <asm/ps3stor.h>
> +
> +
> +#define DEVICE_NAME		"ps3flash"
> +
> +#define FLASH_BLOCK_SIZE	(256*1024)
> +
> +
> +struct ps3flash_private {
> +	struct mutex mutex;	/* Bounce buffer mutex */
> +};
> +#define ps3flash_priv(dev)	((dev)->sbd.core.driver_data)

bzzzt!

> +static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	u64 size = dev->regions[dev->region_idx].size*dev->blk_size;
> +
> +	switch (origin) {
> +	case 1:
> +		offset += file->f_pos;
> +		break;
> +	case 2:
> +		offset += size;
> +		break;
> +	}
> +	if (offset < 0)
> +		return -EINVAL;
> +
> +	file->f_pos = offset;
> +	return file->f_pos;
> +}

lseek implementations usually need locking.  file->f_mapping->host->i_mutex
would be typical.

That locking mostly protects 64-bit f_pos on 32-bit architectures so you
can perahps kinda get away with it here.  However the code is a bit racy
even on 64-bit, for silly userspace.

That being said, I'd have thought that you could use one of our many
generic lseek library fucntions here, or even an newly-exported
block_llseek().  That assumes that i_size is correct, which I trust is the
case.

> +static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
> +			     loff_t *pos)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	struct ps3flash_private *priv = ps3flash_priv(dev);
> +	u64 size, start_sector, end_sector, offset;
> +	ssize_t sectors_read;
> +	size_t remaining, n;
> +
> +	dev_dbg(&dev->sbd.core,
> +		"%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
> +		__func__, __LINE__, count, *pos, buf);
> +
> +	size = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (*pos >= size || !count)
> +		return 0;
> +
> +	if (*pos+count > size) {
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u Truncating count from %zu to %llu\n", __func__,
> +			__LINE__, count, size - *pos);
> +		count = size - *pos;
> +	}
> +
> +	start_sector = do_div_llr(*pos, dev->blk_size, &offset);
> +	end_sector = DIV_ROUND_UP(*pos+count, dev->blk_size);
> +
> +	remaining = count;
> +	do {
> +		mutex_lock(&priv->mutex);
> +
> +		sectors_read = ps3flash_read_sectors(dev, start_sector,
> +						     end_sector-start_sector,
> +						     0);
> +		if (sectors_read < 0) {
> +			mutex_unlock(&priv->mutex);
> +			return sectors_read;
> +		}
> +
> +		n = min(remaining, sectors_read*dev->blk_size-offset);
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
> +			__func__, __LINE__, n, dev->bounce_buf+offset, buf);
> +		if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
> +			mutex_unlock(&priv->mutex);
> +			return -EFAULT;
> +		}
> +
> +		mutex_unlock(&priv->mutex);
> +
> +		*pos += n;
> +		buf += n;
> +		remaining -= n;
> +		start_sector += sectors_read;
> +		offset = 0;
> +	} while (remaining > 0);
> +
> +	return count;
> +}

There are several nasty deeply-embedded return points in this function.

> +static ssize_t ps3flash_write(struct file *file, const char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	struct ps3_storage_device *dev = ps3flash_dev;
> +	struct ps3flash_private *priv = ps3flash_priv(dev);
> +	u64 size, chunk_sectors, start_write_sector, end_write_sector,
> +	    end_read_sector, start_read_sector, head, tail, offset;
> +	ssize_t res;
> +	size_t remaining, n;
> +	unsigned int sec_off;
> +
> +	dev_dbg(&dev->sbd.core,
> +		"%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
> +		__func__, __LINE__, count, *pos, buf);
> +
> +	size = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (*pos >= size || !count)
> +		return 0;
> +
> +	if (*pos+count > size) {

checkpatch missed stuff here.

> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u Truncating count from %zu to %llu\n", __func__,
> +			__LINE__, count, size - *pos);
> +		count = size - *pos;
> +	}
> +
> +	chunk_sectors = dev->bounce_size / dev->blk_size;
> +
> +	start_write_sector = do_div_llr(*pos, dev->bounce_size, &offset) *
> +			     chunk_sectors;

It's strange to see a do_div_llr() in the middle of all this 64-bit-only
code.  Could use / and %?

> +	end_write_sector = DIV_ROUND_UP(*pos+count, dev->bounce_size) *
> +			   chunk_sectors;
> +
> +	end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
> +	start_read_sector = (*pos+count) / dev->blk_size;
> +
> +	/*
> +	 * As we have to write in 256 KiB chunks, while we can read in blk_size
> +	 * (usually 512 bytes) chunks, we perform the following steps:
> +	 *   1. Read from start_write_sector to end_read_sector ("head")
> +	 *   2. Read from start_read_sector to end_write_sector ("tail")
> +	 *   3. Copy data to buffer
> +	 *   4. Write from start_write_sector to end_write_sector
> +	 * All of this is complicated by using only one 256 KiB bounce buffer.
> +	 */
> +
> +	head = end_read_sector-start_write_sector;
> +	tail = end_write_sector-start_read_sector;

checkpatch missed this too.

> +	remaining = count;
> +	do {
> +		mutex_lock(&priv->mutex);
> +
> +		if (end_read_sector >= start_read_sector) {
> +			/* Merge head and tail */
> +			dev_dbg(&dev->sbd.core,
> +				"Merged head and tail: %lu sectors at %lu\n",
> +				chunk_sectors, start_write_sector);
> +			res = ps3flash_read_sectors(dev, start_write_sector,
> +						    chunk_sectors, 0);
> +			if (res < 0)
> +				goto fail;
> +		} else {
> +			if (head) {
> +				/* Read head */
> +				dev_dbg(&dev->sbd.core,
> +					"head: %lu sectors at %lu\n", head,
> +					start_write_sector);
> +				res = ps3flash_read_sectors(dev,
> +							    start_write_sector,
> +							    head, 0);
> +				if (res < 0)
> +					goto fail;
> +			}
> +			if (start_read_sector <
> +			    start_write_sector+chunk_sectors) {
> +				/* Read tail */
> +				dev_dbg(&dev->sbd.core,
> +					"tail: %lu sectors at %lu\n", tail,
> +					start_read_sector);
> +				sec_off = start_read_sector-start_write_sector;
> +				res = ps3flash_read_sectors(dev,
> +							    start_read_sector,
> +							    tail, sec_off);
> +				if (res < 0)
> +					goto fail;
> +			}
> +		}
> +
> +		n = min(remaining, dev->bounce_size-offset);
> +		dev_dbg(&dev->sbd.core,
> +			"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
> +			__func__, __LINE__, n, buf, dev->bounce_buf+offset);
> +		if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
> +			res = -EFAULT;
> +			goto fail;
> +		}
> +
> +		res = ps3flash_write_chunk(dev, start_write_sector);
> +		if (res < 0)
> +			goto fail;
> +
> +		mutex_unlock(&priv->mutex);
> +
> +		*pos += n;
> +		buf += n;
> +		remaining -= n;
> +		start_write_sector += chunk_sectors;
> +		head = 0;
> +		offset = 0;
> +	} while (remaining > 0);
> +
> +	return count;
> +
> +fail:
> +	mutex_unlock(&priv->mutex);
> +	return res;
> +}
>
> ...
>
> +static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
> +{
> +	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
> +	struct ps3flash_private *priv;
> +	int error;
> +	unsigned long tmp;
> +
> +	tmp = dev->regions[dev->region_idx].start*dev->blk_size;
> +	if (tmp % FLASH_BLOCK_SIZE) {
> +		dev_err(&dev->sbd.core,
> +			"%s:%u region start %lu is not aligned\n", __func__,
> +			__LINE__, tmp);
> +		return -EINVAL;
> +	}
> +	tmp = dev->regions[dev->region_idx].size*dev->blk_size;
> +	if (tmp % FLASH_BLOCK_SIZE) {
> +		dev_err(&dev->sbd.core,
> +			"%s:%u region size %lu is not aligned\n", __func__,
> +			__LINE__, tmp);
> +		return -EINVAL;
> +	}
> +
> +	/* use static buffer, kmalloc cannot allocate 256 KiB */
> +	if (!ps3flash_bounce_buffer.address)
> +		return -ENODEV;
> +
> +	if (ps3flash_dev) {
> +		dev_err(&dev->sbd.core,
> +			"Only one FLASH device is supported\n");
> +		return -EBUSY;
> +	}
> +
> +	ps3flash_dev = dev;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		error = -ENOMEM;
> +		goto fail;
> +	}
> +
> +	ps3flash_priv(dev) = priv;
> +	mutex_init(&priv->mutex);
> +
> +	dev->bounce_size = ps3flash_bounce_buffer.size;
> +	dev->bounce_buf = ps3flash_bounce_buffer.address;
> +
> +	error = ps3stor_setup(dev, ps3flash_interrupt);
> +	if (error)
> +		goto fail_free_priv;
> +
> +	ps3flash_misc.parent = &dev->sbd.core;
> +	error = misc_register(&ps3flash_misc);
> +	if (error) {
> +		dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
> +			__func__, __LINE__, error);
> +		goto fail_teardown;
> +	}
> +
> +	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
> +		 __func__, __LINE__, ps3flash_misc.minor);
> +	return 0;
> +
> +fail_teardown:
> +	ps3stor_teardown(dev);
> +fail_free_priv:
> +	kfree(priv);
> +	ps3flash_priv(dev) = NULL;
> +fail:
> +	ps3flash_dev = NULL;
> +	return error;
> +}
> +


  reply	other threads:[~2007-07-18 23:52 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-16 16:15 [patch 0/3] PS3 Storage Drivers for 2.6.23, take 5 Geert Uytterhoeven
2007-07-16 16:15 ` Geert Uytterhoeven
2007-07-16 16:15 ` Geert Uytterhoeven
2007-07-16 16:15 ` [patch 1/3] ps3: Disk Storage Driver Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-18 14:32   ` Jan Engelhardt
2007-07-18 14:32     ` Jan Engelhardt
2007-07-18 14:32     ` Jan Engelhardt
2007-07-18 15:36     ` Geert Uytterhoeven
2007-07-18 15:36       ` Geert Uytterhoeven
2007-07-18 23:36   ` Andrew Morton
2007-07-18 23:36     ` Andrew Morton
2007-07-19  5:33     ` Jens Axboe
2007-07-19  5:33       ` Jens Axboe
2007-07-19  7:15       ` Geert Uytterhoeven
2007-07-19  7:15         ` Geert Uytterhoeven
2007-07-19  7:15         ` Geert Uytterhoeven
2007-07-19  8:57     ` Geert Uytterhoeven
2007-07-19  8:57       ` Geert Uytterhoeven
2007-07-19  8:57       ` Geert Uytterhoeven
2007-07-19  9:10       ` Andrew Morton
2007-07-19  9:10         ` Andrew Morton
2007-07-19 13:52         ` [patch 0/4] PS3 storage driver updates (was: Re: [patch 1/3] ps3: Disk Storage Driver) Geert Uytterhoeven
2007-07-19 13:52           ` Geert Uytterhoeven
2007-07-19 13:53           ` [patch 1/4] ps3disk: use correct bio vector size Geert Uytterhoeven
2007-07-19 13:53             ` Geert Uytterhoeven
2007-07-19 13:54           ` [patch 2/4] ps3disk: updates after final review Geert Uytterhoeven
2007-07-19 13:54             ` Geert Uytterhoeven
2007-07-19 13:54           ` [patch 3/4] ps3rom: " Geert Uytterhoeven
2007-07-19 13:54             ` Geert Uytterhoeven
2007-07-19 13:55           ` [patch 4/4] ps3flash: " Geert Uytterhoeven
2007-07-19 13:55             ` Geert Uytterhoeven
2007-07-19  9:26       ` [patch 1/3] ps3: Disk Storage Driver Cornelia Huck
2007-07-19  9:26         ` Cornelia Huck
2007-07-19  9:36         ` Geert Uytterhoeven
2007-07-19  9:36           ` Geert Uytterhoeven
2007-07-19 12:00           ` Cornelia Huck
2007-07-19 12:00             ` Cornelia Huck
2007-07-19 12:13             ` Geert Uytterhoeven
2007-07-19 12:13               ` Geert Uytterhoeven
2007-07-19 12:52               ` Cornelia Huck
2007-07-19 12:52                 ` Cornelia Huck
2007-07-24 11:44     ` Andy Whitcroft
2007-07-24 11:44       ` Andy Whitcroft
2007-07-24 12:37       ` Jeff Garzik
2007-07-24 12:37         ` Jeff Garzik
2007-07-24 12:52         ` Andreas Schwab
2007-07-24 12:52           ` Andreas Schwab
2007-07-24 12:52           ` Andreas Schwab
2007-07-24 13:44           ` Jeff Garzik
2007-07-24 13:44             ` Jeff Garzik
2007-07-24 16:43         ` Andrew Morton
2007-07-24 16:43           ` Andrew Morton
2007-07-24 16:43           ` Andrew Morton
2007-07-25  1:09       ` Paul Mackerras
2007-07-25  1:09         ` Paul Mackerras
2007-07-25  1:21         ` Andrew Morton
2007-07-25  1:21           ` Andrew Morton
2007-07-16 16:15 ` [patch 2/3] ps3: BD/DVD/CD-ROM " Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-18 23:43   ` Andrew Morton
2007-07-18 23:43     ` Andrew Morton
2007-07-19  9:02     ` Geert Uytterhoeven
2007-07-19  9:02       ` Geert Uytterhoeven
2007-07-19  9:02       ` Geert Uytterhoeven
2007-07-19  9:17       ` Andrew Morton
2007-07-19  9:17         ` Andrew Morton
2007-07-19  9:39         ` Geert Uytterhoeven
2007-07-19  9:39           ` Geert Uytterhoeven
2007-07-19  9:41           ` Jens Axboe
2007-07-19  9:41             ` Jens Axboe
2007-07-19  9:47           ` Andrew Morton
2007-07-19  9:47             ` Andrew Morton
2007-07-19  9:47             ` Andrew Morton
2007-07-19 17:56             ` Rene Herman
2007-07-19 17:56               ` Rene Herman
2007-07-16 16:15 ` [patch 3/3] ps3: FLASH ROM " Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-16 16:15   ` Geert Uytterhoeven
2007-07-18 23:52   ` Andrew Morton [this message]
2007-07-18 23:52     ` Andrew Morton
2007-07-19 11:25     ` Geert Uytterhoeven
2007-07-19 11:25       ` Geert Uytterhoeven
2007-07-19  6:40 ` [patch 0/3] PS3 Storage Drivers for 2.6.23, take 5 Alessandro Rubini
2007-07-19  6:40   ` Alessandro Rubini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070718165222.e504d92e.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=Geert.Uytterhoeven@sonycom.com \
    --cc=James.Bottomley@SteelEye.com \
    --cc=apw@shadowen.org \
    --cc=axboe@kernel.dk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=paulus@samba.org \
    --cc=rubini@vision.unipv.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.