[Fwd: Re: [PATCH] 2/2 mtd: Add support for the Dreamcast VMU flash]
Jörn Engel
joern at logfs.org
Thu Mar 20 06:03:53 EDT 2008
Some details I noticed on first glance.
On Wed, 19 March 2008 21:20:41 +0000, Adrian McMenamin wrote:
>
> +/* Interface with maple bus to read bytes */
> +static int maple_vmu_read_block(unsigned int num, unsigned char *buf,
> + struct mtd_info *mtd)
> +{
> + struct memcard *card;
> + struct mdev_part *mpart;
> + struct maple_device *mdev;
> + int partition, error, locking;
> + void *sendbuf;
> +
> + mpart = mtd->priv;
> + mdev = mpart->mdev;
> + partition = mpart->partition;
> + card = mdev->private_data;
> +
> + /* wait for the mutex to be available */
> + locking = down_interruptible(&(mdev->mq->sem));
> + if (locking) {
> + printk(KERN_INFO "Maple: VMU at (%d, %d) is locked -"
> + " aborting read\n", mdev->unit, mdev->port);
> + goto fail_nosendbuf;
> + }
> + mdev->mq->command = MAPLE_COMMAND_BREAD;
> + mdev->mq->length = 2;
> +
> + sendbuf = kzalloc(mdev->mq->length * 4, GFP_KERNEL);
> + if (!sendbuf) {
> + error = -ENOMEM;
> + goto fail_nosendbuf;
> + }
> +
> + ((unsigned long *)sendbuf)[0] = cpu_to_be32(MAPLE_FUNC_MEMCARD);
> + ((unsigned long *)sendbuf)[1] = cpu_to_be32(partition << 24 | num);
unsigned long is larger than 32bit on many architectures. Better
variant:
__be32 *sendbuf;
...
sendbuf[0] = cpu_to_be32(MAPLE_FUNC_MEMCARD);
sendbuf[1] = cpu_to_be32(partition << 24 | num);
Sparse would have noticed this problem as well. Might be a good idea to
$ make C=1 drivers/mtd/maps/vmu_flash.o
and take a look what other problems show up.
> + mdev->mq->sendbuf = sendbuf;
Possibly the big-endian annotations need to trickly though the layers
here as well.
> +/* mtd function to simulate reading byte by byte */
> +static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval,
> + struct mtd_info *mtd)
> +{
> + struct vmu_block *vblock;
> + struct memcard *card;
> + struct mdev_part *mpart;
> + struct maple_device *mdev;
> + unsigned char *buf, ret;
> + int partition, error;
> +
> + mpart = mtd->priv;
> + mdev = mpart->mdev;
> + partition = mpart->partition;
> + card = mdev->private_data;
> + *retval = 0;
> + buf = kmalloc(card->blocklen, GFP_KERNEL);
> + if (!buf) {
> + *retval = 1;
> + error = ENOMEM;
> + goto fail_buffer;
> + }
> +
> + vblock = ofs_to_block(ofs, mtd, partition);
> + if (!vblock) {
> + *retval = 3;
> + error = ENOMEM;
> + goto invalid_block;
> + }
> +
> + error = maple_vmu_read_block(vblock->num, buf, mtd);
> + if (error) {
> + *retval = 2;
> + goto failed_block;
> + }
> + ret = buf[vblock->ofs];
> + kfree(buf);
> + kfree(vblock);
> + return ret;
> +
> +failed_block:
> + kfree(vblock);
> +invalid_block:
> + kfree(buf);
> +fail_buffer:
> + return -error;
Yikes. Errnos greater 127 do exist. Better return a signed int and
interpret at error if <0.
You could also combine the two sets of kfree() into one, btw.
> + do {
> + if (pcache->valid &&
> + time_before(jiffies, pcache->jiffies_atc + HZ)) {
> + vblock = ofs_to_block(from + index, mtd, partition);
> + if (!vblock)
> + return -ENOMEM;
> + if (pcache->block == vblock->num) {
> + /*we have cached it, so do necessary copying */
> + leftover = card->blocklen - vblock->ofs;
> + if (leftover > len - index) {
> + /* only a bit of this block to copy */
> + memcpy(buf + index,
> + pcache->buffer + vblock->ofs,
> + len - index);
Five levels of indentation are a strong indication that this code is
buggy. I don't understand how it behaves in all corner cases and I bet
neither do you.
> + do {
> +
> + /* Read in the block we are to write to */
> + if (maple_vmu_read_block(vblock->num, buffer, mtd)) {
> + error = -EIO;
> + goto fail_io;
> + }
> +
> + do {
> + buffer[vblock->ofs] = buf[index];
> + vblock->ofs++;
> + index++;
> + if (index >= len)
> + break;
> + } while (vblock->ofs < card->blocklen);
> + /* write out new buffer */
> + retval = maple_vmu_write_block(vblock->num, buffer, mtd);
> + /* invalidare the cache */
> + pcache = (card->parts[partition]).pcache;
> + pcache->valid = 0;
> +
> + if (retval != card->blocklen) {
> + error = -EIO;
> + goto fail_io;
> + }
> +
> + vblock->num++;
> + vblock->ofs = 0;
> + } while (len > index);
And here is an example of essentially the same loop in a fashion mere
mortals can understand. Much better. ;)
> +MODULE_AUTHOR("Adrian McMenamin, Paul Mundt");
I believe the main use of MODULE_AUTHOR is to figure out who to send bug
reports/patches to, not to contain every possible copyright holder. So
possibly just your name here would be more appropriate.
Jörn
--
A victorious army first wins and then seeks battle.
-- Sun Tzu
More information about the linux-mtd
mailing list