public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
From: Mitch Bradley <wmb@firmworks.com>
To: Mitch Bradley <wmb@firmworks.com>,
	linuxppc-dev@ozlabs.org, linux-mtd@lists.infradead.org,
	david@gibson.dropbear.id.au
Subject: Re: [PATCH] Support NAND partitions >4GiB with Open Firmware
Date: Thu, 26 Jun 2008 17:28:42 -1000	[thread overview]
Message-ID: <48645E6A.6020202@firmworks.com> (raw)
In-Reply-To: <20080627032046.GH17621@yookeroo.seuss>



David Gibson wrote:
> On Thu, Jun 26, 2008 at 01:50:40PM -1000, Mitch Bradley wrote:
>   
>> This patch modifes ofpart.c so the total size of NAND FLASH
>> and the size of an individual partition can exceed 4GiB.  It does so
>> by decoding the "reg" property based on the values of "#address-cells"
>> and "#size-cells" in the parent node, thus allowing the base address
>> and size to be 64-bit numbers if necessary.  It handles any combination
>> of #address-cells = 1 or 2 and #size-cells = 1 or 2, handles the case
>> where the parent node doesn't have #address-cells / #size-cells properties,
>> and handles the case where the value of #address-cells is incorrectly
>> inherited from farther up the tree than the direct parent.
>>
>> This patch does not solve the problem that the MTD subsystem
>> itself is limited to 2 GiB NAND sizes, but it is a step in that direction.
>> The final assignment of the 64-bit partition offset and size values is
>> truncated (by the C type conversion rules) to the actual size of the
>> struct mtd_partition offset and size fields (which are currently u_int32's).
>> At some point in the future, when those fields become larger, the code
>> should "just work".
>>
>> The patch should apply to either 2.6.25 or 2.6.26rc.  It has been tested
>> on the OLPC variant of 2.6.25 , with additional patches to other
>> OLPC-specific files that aren't necessary for other architectures
>> that have more mature support for Open Firmware.  The OLPC
>> patch set, plus a set of test cases that verify correct operation for
>> various #address-cells / #size-cells combinations, can be found at
>> http://dev.laptop.org/~wmb/ofpart-olpc.tgz
>>     
>
> I like the idea - but there are some uglies in the implementation.
>
>   
>> Signed-off-by: Mitch Bradley <wmb@firmworks.com>
>>
>> diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
>> index f86e069..b83b26c 100644
>> --- a/drivers/mtd/ofpart.c
>> +++ b/drivers/mtd/ofpart.c
>> @@ -7,6 +7,10 @@
>>  * Revised to handle newer style flash binding by:
>>  *   Copyright (C) 2007 David Gibson, IBM Corporation.
>>  *
>> + * Revised to handle multi-cell addresses and size in reg properties,
>> + * paving the way for NAND FLASH devices > 4GiB by:
>> + *   Mitch Bradley <wmb@laptop.org>
>> + *
>>  * 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;  either version 2 of the  License, or (at your
>> @@ -15,0 +19,0 @@
>>
>> #include <linux/module.h>
>> #include <linux/init.h>
>> +#include <linux/device.h>
>> #include <linux/of.h>
>> #include <linux/mtd/mtd.h>
>> #include <linux/mtd/partitions.h>
>>
>> +u_int32_t decode_cell(const u_int8_t *prop)
>> +{
>> +       return ((prop[0] << 24) + (prop[1] << 16) + (prop[2] << 8) +  
>> prop[3]);
>> +}
>>     
>
> You don't appear to actually use this new function.
>   

It's already gone in the new version (the announcement of which may have 
been delayed by the mailing list of which I'm not a subscriber).
>   
>> int __devinit of_mtd_parse_partitions(struct device *dev,
>>                                       struct mtd_info *mtd,
>>                                       struct device_node *node,
>> @@ -44,5 +54,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
>>        pp = NULL;
>>        i = 0;
>>        while ((pp = of_get_next_child(node, pp))) {
>> -               const u32 *reg;
>> +               u_int64_t xoffset, xsize;
>>     
>
> The names u64 and u32 are preferred for kernel internal things.
> Certainly not u_int64_t which isn't even the C99 standard name.
>   

Already fixed.

>   
>> +               const u_int32_t *propval;
>> +               u_int32_t addrcells = 0, sizecells = 0;
>>                int len;
>>
>> -               reg = of_get_property(pp, "reg", &len);
>> -               if (!reg || (len != 2 * sizeof(u32))) {
>> +               /*
>> +                * Determine the layout of a "reg" entry based on the parent
>> +                * node's properties, if it hasn't been done already.
>> +                */
>> +
>> +               if (addrcells == 0)
>>     
>
> Redundant 'if'; you've just initialized this variable to zero.
>   

The intention is that the body of the "if" should only be executed
once during the loop, since the parent node is the same for all children.

>   
>> +                       addrcells = of_n_addr_cells(pp);
>> +               if (sizecells == 0)
>> +                       sizecells = of_n_size_cells(pp);
>> +
>> +               propval = of_get_property(pp, "reg", &len);
>> +
>> +               /*
>> +                * Handle the possibility of a broken device tree that
>> +                * doesn't define #address-cells and #size-cells properly.
>> +                 * In a standard device tree, if the address portion of
>> +                 * "reg" is one cell, the direct parent should have a
>> +                 * #address-cells property with value 1.
>> +                */
>> +               if (propval && (len == 2 * sizeof(u32)))
>> +                       addrcells = sizecells = 1;
>> +
>> +               /* Error checks */
>> +
>> +               if (addrcells < 1 || addrcells > 2) {
>> +                       of_node_put(pp);
>> +                       dev_err(dev, "Invalid #address_cells %d on %s\n",
>> +                               addrcells, node->full_name);
>> +                       kfree(*pparts);
>> +                       *pparts = NULL;
>> +                       return -EINVAL;
>> +               }
>> +
>> +               if (sizecells < 1 || sizecells > 2) {
>> +                       of_node_put(pp);
>> +                       dev_err(dev, "Invalid #size-cells %d on %s\n",
>> +                               sizecells, node->full_name);
>> +                       kfree(*pparts);
>> +                       *pparts = NULL;
>> +                       return -EINVAL;
>> +               }
>> +
>> +               if (!propval || (len != (addrcells+sizecells) *  
>> sizeof(u32))) {
>>                        of_node_put(pp);
>>                        dev_err(dev, "Invalid 'reg' on %s\n",  
>> node->full_name);
>>                        kfree(*pparts);
>>                        *pparts = NULL;
>>                        return -EINVAL;
>>                }
>> -               (*pparts)[i].offset = reg[0];
>> -               (*pparts)[i].size = reg[1];
>> +
>> +               /* Accumulate the base address and size into 64-bit  
>> numbers */
>> +               xoffset = (u_int64_t)ntohl(propval[0]);
>>     
>
> You shouldn't use the ntohl() names outside of networking code.
> Instead use be32_to_cpu() and the like.
>   

That whole code block has been replaced by a call to of_read_number()

>   
>> +               if (addrcells > 1) {
>> +                       xoffset <<= 32;
>> +                       xoffset += ntohl(propval[1]);
>> +               }
>> +               xsize = (u_int64_t)ntohl(propval[addrcells]);
>> +               if (sizecells > 1) {
>> +                       xsize <<= 32;
>> +                       xsize += ntohl(propval[addrcells+1]);
>> +               }
>> +
>> +               (*pparts)[i].offset = xoffset;
>> +               (*pparts)[i].size = xsize;
>>
>>                partname = of_get_property(pp, "label", &len);
>>                if (!partname)
>>     
>
>   

  reply	other threads:[~2008-06-27  3:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-26 23:50 [PATCH] Support NAND partitions >4GiB with Open Firmware Mitch Bradley
2008-06-27  3:09 ` Mitch Bradley
2008-06-27  3:20 ` David Gibson
2008-06-27  3:28   ` Mitch Bradley [this message]
2008-06-27  3:38     ` David Gibson
2008-06-27  3:48       ` Mitch Bradley
2008-06-27  4:04         ` David Gibson

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=48645E6A.6020202@firmworks.com \
    --to=wmb@firmworks.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linuxppc-dev@ozlabs.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox