[PATCH (Option 1)] of/i2c: fix module load order issue caused by of_i2c.c

Grant Likely grant.likely at secretlab.ca
Wed Sep 29 09:26:03 EST 2010


On Wed, Sep 29, 2010 at 8:21 AM, Ben Dooks <ben-i2c at fluff.org> wrote:
> On Fri, Sep 24, 2010 at 04:14:53PM -0600, Grant Likely wrote:
>> Commit 959e85f7, "i2c: add OF-style registration and binding" caused a
>> module dependency loop where of_i2c.c calls functions in i2c-core, and
>> i2c-core calls of_i2c_register_devices() in of_i2c.  This means that
>> when i2c support is built as a module when CONFIG_OF is set, then
>> neither i2c_core nor of_i2c are able to be loaded.
>>
>> This patch fixes the problem by moving the of_i2c_register_devices()
>> function into the body of i2c_core and renaming it to
>> i2c_scan_of_devices (of_i2c_register_devices is analogous to the
>> existing i2c_scan_static_board_info function and so should be named
>> similarly).  This function isn't called by any code outside of
>> i2c_core, and it must always be present when CONFIG_OF is selected, so
>> it makes sense to locate it there.  When CONFIG_OF is not selected,
>> of_i2c_register_devices() becomes a no-op.
>>
>> Signed-off-by: Grant Likely <grant.likely at secretlab.ca>
>> ---
>>  drivers/i2c/i2c-core.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++--
>>  drivers/of/of_i2c.c    |   57 ---------------------------------------------
>>  include/linux/of_i2c.h |    7 ------
>>  3 files changed, 59 insertions(+), 66 deletions(-)
>>
>> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
>> index 6649176..64a261b 100644
>> --- a/drivers/i2c/i2c-core.c
>> +++ b/drivers/i2c/i2c-core.c
>> @@ -32,8 +32,8 @@
>>  #include <linux/init.h>
>>  #include <linux/idr.h>
>>  #include <linux/mutex.h>
>> -#include <linux/of_i2c.h>
>>  #include <linux/of_device.h>
>> +#include <linux/of_irq.h>
>>  #include <linux/completion.h>
>>  #include <linux/hardirq.h>
>>  #include <linux/irqflags.h>
>> @@ -818,6 +818,63 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
>>       up_read(&__i2c_board_lock);
>>  }
>>
>> +#ifdef CONFIG_OF
>> +void i2c_scan_of_devices(struct i2c_adapter *adap)
>> +{
>> +     void *result;
>> +     struct device_node *node;
>> +
>> +     /* Only register child devices if the adapter has a node pointer set */
>> +     if (!adap->dev.of_node)
>> +             return;
>> +
>> +     for_each_child_of_node(adap->dev.of_node, node) {
>> +             struct i2c_board_info info = {};
>> +             struct dev_archdata dev_ad = {};
>> +             const __be32 *addr;
>> +             int len;
>> +
>> +             dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
>> +             if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
>> +                     dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
>> +                             node->full_name);
>> +                     continue;
>> +             }
>> +
>> +             addr = of_get_property(node, "reg", &len);
>> +             if (!addr || (len < sizeof(int))) {
>> +                     dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
>> +                             node->full_name);
>> +                     continue;
>> +             }
>> +
>> +             info.addr = be32_to_cpup(addr);
>> +             if (info.addr > (1 << 10) - 1) {
>> +                     dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
>> +                             info.addr, node->full_name);
>> +                     continue;
>> +             }
>> +
>> +             info.irq = irq_of_parse_and_map(node, 0);
>> +             info.of_node = of_node_get(node);
>> +             info.archdata = &dev_ad;
>> +
>> +             request_module("%s", info.type);
>> +
>> +             result = i2c_new_device(adap, &info);
>> +             if (result == NULL) {
>> +                     dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
>> +                             node->full_name);
>> +                     of_node_put(node);
>> +                     irq_dispose_mapping(info.irq);
>> +                     continue;
>> +             }
>> +     }
>> +}
>> +#else
>> +static inline void i2c_scan_of_devices(struct i2c_adapter *adap) { }
>> +#endif
>
> Is there any advantage to just making the definition in the header
> file a static inline and removing the #else part of this?

I'm not sure what you mean.  This particular patch makes
i2c_scan_of_devices() completely internal to i2c-core.c so that there
is no need to expose it in the header file at all.

g.

>
> --
> Ben
>
> Q:      What's a light-year?
> A:      One-third less calories than a regular year.
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.


More information about the Linuxppc-dev mailing list