Message ID | 2144222.LfzPx9mJ0p@wuerfel (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
On Thu, Dec 10, 2015 at 02:14:49PM +0100, Arnd Bergmann wrote: > The emev2 driver stopped compiling in today's linux-next kernel: > > drivers/i2c/busses/i2c-emev2.c: In function 'em_i2c_slave_irq': > drivers/i2c/busses/i2c-emev2.c:233:23: error: storage size of 'event' isn't known > drivers/i2c/busses/i2c-emev2.c:250:3: error: implicit declaration of function 'i2c_slave_event' [-Werror=implicit-function-declaration] > drivers/i2c/busses/i2c-emev2.c:250:32: error: 'I2C_SLAVE_STOP' undeclared (first use in this function) > > It works again if we enable CONFIG_I2C_SLAVE, but it seems wrong > to add a dependency on that symbol: > > * The symbol is user-selectable, but only one or two (including this > one) bus drivers actually implement it, and it makes no sense > if you don't have one of them. > > * The other driver (R-Car) uses 'select I2C_SLAVE', which seems > reasonable in principle, but we should not do that on user > visible symbols. > > * I2C slave mode could be implemented in a lot of other drivers > as an optional feature, but we shouldn't require enabling it > if we don't use it. > > This changes the two drivers that provide I2C slave mode so they > can again build if the slave mode being disabled. To do this, I > move the definition of i2c_slave_event() and enum i2c_slave_event > out of the #ifdef and instead make the assignment of the reg_slave > and unreg_slave pointers optional in the bus drivers. The functions > implementing the feature are unused in that case, so they get > marked as __maybe_unused in order to still give compile-time > coverage. Thanks a lot! Making this clear and consistent was on my todo-list, unfortunately below some other items. Both drivers have quite orthogonal slave_irq routines. What do you think about grouping this and the reg/unreg-calls together and compile them conditionally on I2C_SLAVE? I think the code savings are worth it.
Hi Arnd,
[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on next-20151210]
[cannot apply to v4.4-rc4]
url: https://github.com/0day-ci/linux/commits/Arnd-Bergmann/i2c-allow-building-emev2-without-slave-mode-again/20151210-211642
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux i2c/for-next
config: x86_64-randconfig-r0-12102217 (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
In file included from arch/x86/include/asm/realmode.h:5:0,
from arch/x86/include/asm/acpi.h:33,
from arch/x86/include/asm/fixmap.h:19,
from arch/x86/include/asm/apic.h:12,
from arch/x86/include/asm/smp.h:12,
from arch/x86/include/asm/mmzone_64.h:10,
from arch/x86/include/asm/mmzone.h:4,
from include/linux/mmzone.h:856,
from include/linux/gfp.h:5,
from include/linux/device.h:29,
from drivers/i2c/busses/i2c-emev2.c:15:
drivers/i2c/busses/i2c-emev2.c: In function 'em_i2c_irq_handler':
>> arch/x86/include/asm/io.h:53:3: warning: 'value' may be used uninitialized in this function [-Wmaybe-uninitialized]
{ asm volatile("mov" size " %0,%1": :reg (val), \
^
drivers/i2c/busses/i2c-emev2.c:232:13: note: 'value' was declared here
u8 status, value;
^
vim +/value +53 arch/x86/include/asm/io.h
b310f381d include/asm-x86/io.h venkatesh.pallipadi@intel.com 2008-03-18 37 #define ARCH_HAS_IOREMAP_WC
d838270e2 arch/x86/include/asm/io.h Toshi Kani 2015-06-04 38 #define ARCH_HAS_IOREMAP_WT
b310f381d include/asm-x86/io.h venkatesh.pallipadi@intel.com 2008-03-18 39
1c5b9069e arch/x86/include/asm/io.h Brian Gerst 2010-02-05 40 #include <linux/string.h>
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 41 #include <linux/compiler.h>
976e8f677 arch/x86/include/asm/io.h Jeremy Fitzhardinge 2009-02-06 42 #include <asm/page.h>
5b7c73e00 arch/x86/include/asm/io.h Mark Salter 2014-04-07 43 #include <asm/early_ioremap.h>
d6472302f arch/x86/include/asm/io.h Stephen Rothwell 2015-06-02 44 #include <asm/pgtable_types.h>
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 45
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 46 #define build_mmio_read(name, size, type, reg, barrier) \
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 47 static inline type name(const volatile void __iomem *addr) \
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 48 { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 49 :"m" (*(volatile type __force *)addr) barrier); return ret; }
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 50
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 51 #define build_mmio_write(name, size, type, reg, barrier) \
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 52 static inline void name(type val, volatile void __iomem *addr) \
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 @53 { asm volatile("mov" size " %0,%1": :reg (val), \
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 54 "m" (*(volatile type __force *)addr) barrier); }
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 55
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 56 build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 57 build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 58 build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
c1f64a580 include/asm-x86/io.h Linus Torvalds 2008-05-27 59
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 60 build_mmio_read(__readb, "b", unsigned char, "=q", )
1c5b0eb66 include/asm-x86/io.h Mikael Pettersson 2008-08-13 61 build_mmio_read(__readw, "w", unsigned short, "=r", )
:::::: The code at line 53 was first introduced by commit
:::::: c1f64a58003fd2efaa725a857e269a15f765791a x86: MMIO and gcc re-ordering issue
:::::: TO: Linus Torvalds <torvalds@linux-foundation.org>
:::::: CC: Ingo Molnar <mingo@elte.hu>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Thursday 10 December 2015 22:54:25 kbuild test robot wrote: > > In file included from arch/x86/include/asm/realmode.h:5:0, > from arch/x86/include/asm/acpi.h:33, > from arch/x86/include/asm/fixmap.h:19, > from arch/x86/include/asm/apic.h:12, > from arch/x86/include/asm/smp.h:12, > from arch/x86/include/asm/mmzone_64.h:10, > from arch/x86/include/asm/mmzone.h:4, > from include/linux/mmzone.h:856, > from include/linux/gfp.h:5, > from include/linux/device.h:29, > from drivers/i2c/busses/i2c-emev2.c:15: > drivers/i2c/busses/i2c-emev2.c: In function 'em_i2c_irq_handler': > >> arch/x86/include/asm/io.h:53:3: warning: 'value' may be used uninitialized in this function [-Wmaybe-uninitialized] > { asm volatile("mov" size " %0,%1": :reg (val), \ > ^ > drivers/i2c/busses/i2c-emev2.c:232:13: note: 'value' was declared here > u8 status, value; > ^ The warning was indeed introduced by my change, but I think there was a preexisting issue: The slave_cb callback function is supposed to set the 'value' here, but it might return an error not assign the pointer, which is something that both the rcar and the emev2 drivers do not handle correctly. It might be best to change the callback to return 'void' and not allow it to fail. At least the eeprom slave cannot fail anyway, and it is the only implementation we have at the moment. The inline function would then have to be changed to initialize the 'value'. Alternatively, the inline could return an error, and both bus drivers check for the error before using 'value'. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> Alternatively, the inline could return an error, and both bus > drivers check for the error before using 'value'. I'll try to check these options tomorrow.
Hi Arnd, thanks for looking into this, but I don't get your point yet. > The slave_cb callback function is supposed to set the 'value' > here, Only if a master wants to READ from us. > but it might return an error not assign the pointer, An error is only returned if a WRITE from a master was not accepted by the slave backend. > It might be best to change the callback to return 'void' and not > allow it to fail. We need that because in case of an errno, the slave should send NACK to the master instead of ACK. > At least the eeprom slave cannot fail anyway, and it is the only > implementation we have at the moment. True. But giving a slave the possibility to NACK a write should be present IMO. > Alternatively, the inline could return an error, and both bus > drivers check for the error before using 'value'. Hum, it does return an error? return client->slave_cb(client, event, val); You probably mean something else? Regards, Wolfram
On Saturday 12 December 2015 17:20:57 Wolfram Sang wrote: > Hi Arnd, > > thanks for looking into this, but I don't get your point yet. > > > The slave_cb callback function is supposed to set the 'value' > > here, > > Only if a master wants to READ from us. Right, and can this never fail? > > but it might return an error not assign the pointer, > > An error is only returned if a WRITE from a master was not accepted by > the slave backend. > > > It might be best to change the callback to return 'void' and not > > allow it to fail. > > We need that because in case of an errno, the slave should send NACK to > the master instead of ACK. > > > At least the eeprom slave cannot fail anyway, and it is the only > > implementation we have at the moment. > > True. But giving a slave the possibility to NACK a write should be > present IMO. Ok, fair enough. > > Alternatively, the inline could return an error, and both bus > > drivers check for the error before using 'value'. > > Hum, it does return an error? > > return client->slave_cb(client, event, val); > > You probably mean something else? I mean specifically this code in em_i2c_slave_irq(): /* Send data */ event = status & I2C_BIT_STD0 ? I2C_SLAVE_READ_REQUESTED : I2C_SLAVE_READ_PROCESSED; i2c_slave_event(priv->slave, event, &value); writeb(value, priv->base + I2C_OFS_IIC0); With my current code to turn i2c_slave_event() into an empty inline function in case of !CONFIG_I2C_SLAVE, the compiler knows that "value" is uninitialized at the point where we write it to the register, and warns about it. The code will of course never run if slave mode is not allowed, but we should still shut up the warning, either by making the inline i2c_slave_event set 'value' to zero or 0xff, or by adding an error check: ret = i2c_slave_event(priv->slave, event, &value); if (!ret) writeb(value, priv->base + I2C_OFS_IIC0); and making the empty i2c_slave_event() function return -ENOSYS or -ENOTSUPP. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> > > The slave_cb callback function is supposed to set the 'value' > > > here, > > > > Only if a master wants to READ from us. > > Right, and can this never fail? Exactly. The slave can stretch the clock if the value to be sent to the master needs some processing first, but it must deliver something. > With my current code to turn i2c_slave_event() into an empty inline function > in case of !CONFIG_I2C_SLAVE, the compiler knows that "value" is uninitialized > at the point where we write it to the register, and warns about it. I overlooked that your first patch changed this code, sorry. Now I see the problem. What about not ifdeffing the inline function and keep the build error whenever someone uses it without I2C_SLAVE being selected? Thanks, Wolfram
On Sunday 13 December 2015 10:09:59 Wolfram Sang wrote: > > What about not ifdeffing the inline function and keep the build error > whenever someone uses it without I2C_SLAVE being selected? The inline function is only added there for the case that I2C_SLAVE is disabled, so that would be pointless. However, what we could do is move the extern declaration outside of the #ifdef to make it always visible. The if(IS_ENABLED(CONFIG_I2C_SLAVE)) check should then ensure that it never actually gets called, and we get a link error if some driver gets it wrong. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> > What about not ifdeffing the inline function and keep the build error > > whenever someone uses it without I2C_SLAVE being selected? > > The inline function is only added there for the case that I2C_SLAVE is > disabled, so that would be pointless. > > However, what we could do is move the extern declaration outside of > the #ifdef to make it always visible. The if(IS_ENABLED(CONFIG_I2C_SLAVE)) > check should then ensure that it never actually gets called, and we > get a link error if some driver gets it wrong. Yes, that's what I meant: move the whole function (as it was before your patch) out of the CONFIG_I2C_SLAVE block. We should get a compiler error even, because for !I2C_SLAVE, the client struct will not have the slave_cb member.
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 69c46fe13777..1c8d53f34dd3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -985,7 +985,6 @@ config I2C_XLP9XX config I2C_RCAR tristate "Renesas R-Car I2C Controller" depends on ARCH_SHMOBILE || COMPILE_TEST - select I2C_SLAVE help If you say yes to this option, support will be included for the R-Car I2C controller. diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 96bb4e749012..75d6095c5fe1 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -316,7 +316,7 @@ static u32 em_i2c_func(struct i2c_adapter *adap) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE; } -static int em_i2c_reg_slave(struct i2c_client *slave) +static int __maybe_unused em_i2c_reg_slave(struct i2c_client *slave) { struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); @@ -334,7 +334,7 @@ static int em_i2c_reg_slave(struct i2c_client *slave) return 0; } -static int em_i2c_unreg_slave(struct i2c_client *slave) +static int __maybe_unused em_i2c_unreg_slave(struct i2c_client *slave) { struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); @@ -350,8 +350,10 @@ static int em_i2c_unreg_slave(struct i2c_client *slave) static struct i2c_algorithm em_i2c_algo = { .master_xfer = em_i2c_xfer, .functionality = em_i2c_func, +#ifdef CONFIG_I2C_SLAVE .reg_slave = em_i2c_reg_slave, .unreg_slave = em_i2c_unreg_slave, +#endif }; static int em_i2c_probe(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 3ed1f0aa5eeb..e67824adeba0 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -521,7 +521,7 @@ out: return ret; } -static int rcar_reg_slave(struct i2c_client *slave) +static int __maybe_unused rcar_reg_slave(struct i2c_client *slave) { struct rcar_i2c_priv *priv = i2c_get_adapdata(slave->adapter); @@ -542,7 +542,7 @@ static int rcar_reg_slave(struct i2c_client *slave) return 0; } -static int rcar_unreg_slave(struct i2c_client *slave) +static int __maybe_unused rcar_unreg_slave(struct i2c_client *slave) { struct rcar_i2c_priv *priv = i2c_get_adapdata(slave->adapter); @@ -568,8 +568,10 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm rcar_i2c_algo = { .master_xfer = rcar_i2c_master_xfer, .functionality = rcar_i2c_func, +#ifdef CONFIG_I2C_SLAVE .reg_slave = rcar_reg_slave, .unreg_slave = rcar_unreg_slave, +#endif }; static const struct of_device_id rcar_i2c_dt_ids[] = { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 51028f351d13..69871e5ee44a 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -254,7 +254,6 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) /* I2C slave support */ -#if IS_ENABLED(CONFIG_I2C_SLAVE) enum i2c_slave_event { I2C_SLAVE_READ_REQUESTED, I2C_SLAVE_WRITE_REQUESTED, @@ -269,9 +268,12 @@ extern int i2c_slave_unregister(struct i2c_client *client); static inline int i2c_slave_event(struct i2c_client *client, enum i2c_slave_event event, u8 *val) { +#if IS_ENABLED(CONFIG_I2C_SLAVE) return client->slave_cb(client, event, val); -} +#else + return 0; #endif +} /** * struct i2c_board_info - template for device creation
The emev2 driver stopped compiling in today's linux-next kernel: drivers/i2c/busses/i2c-emev2.c: In function 'em_i2c_slave_irq': drivers/i2c/busses/i2c-emev2.c:233:23: error: storage size of 'event' isn't known drivers/i2c/busses/i2c-emev2.c:250:3: error: implicit declaration of function 'i2c_slave_event' [-Werror=implicit-function-declaration] drivers/i2c/busses/i2c-emev2.c:250:32: error: 'I2C_SLAVE_STOP' undeclared (first use in this function) It works again if we enable CONFIG_I2C_SLAVE, but it seems wrong to add a dependency on that symbol: * The symbol is user-selectable, but only one or two (including this one) bus drivers actually implement it, and it makes no sense if you don't have one of them. * The other driver (R-Car) uses 'select I2C_SLAVE', which seems reasonable in principle, but we should not do that on user visible symbols. * I2C slave mode could be implemented in a lot of other drivers as an optional feature, but we shouldn't require enabling it if we don't use it. This changes the two drivers that provide I2C slave mode so they can again build if the slave mode being disabled. To do this, I move the definition of i2c_slave_event() and enum i2c_slave_event out of the #ifdef and instead make the assignment of the reg_slave and unreg_slave pointers optional in the bus drivers. The functions implementing the feature are unused in that case, so they get marked as __maybe_unused in order to still give compile-time coverage. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: c31d0a00021d ("i2c: emev2: add slave support") -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html