(i2c part merged upstream) (dvb part initialization moved to _frontend_attach() and submitted) From EMAIL_REMOVED Wed Oct 18 18:37:23 2006 Date: Wed, 18 Oct 2006 18:37:20 +0200 (CEST) From: Jiri Kosina To: Jean Delvare Cc: Patrick Boettcher , Mauro Carvalho Chehab , , Subject: [PATCH] 0/2: I2C && DVB: fix recursive locking lockped warning in i2c_transfer() 1/2 adds the 'level' field into the i2c_adapter structure, which is used to represent the 'logical' level of nesting for the purposes of lockdep. This field is then used in the i2c_transfer() function, to acquire the per-adapter bus_lock with correct nesting level. 2/2 adds proper setting of this 'level' parameter in the DVB layer. These two patches are confirmed to fix the following warning: ============================================= [ INFO: possible recursive locking detected ] 2.6.19-rc1-mm1 #4 --------------------------------------------- khubd/451 is trying to acquire lock: (&adap->bus_lock){--..}, at: [] i2c_transfer+0x23/0x40 [i2c_core] but task is already holding lock: (&adap->bus_lock){--..}, at: [] i2c_transfer+0x23/0x40 [i2c_core] other info that might help us debug this: 1 lock held by khubd/451: #0: (&adap->bus_lock){--..}, at: [] i2c_transfer+0x23/0x40 [i2c_core] stack backtrace: [] dump_trace+0x65/0x1a2 [] show_trace_log_lvl+0x10/0x20 [] show_trace+0xa/0xc [] dump_stack+0x13/0x15 [] __lock_acquire+0x7bd/0xa05 [] lock_acquire+0x5c/0x7b [] __mutex_lock_slowpath+0xab/0x1de [] i2c_transfer+0x23/0x40 [i2c_core] [] dibx000_i2c_gated_tuner_xfer+0x166/0x185 [dibx000_common] [] i2c_transfer+0x2f/0x40 [i2c_core] [] mt2060_readreg+0x4b/0x69 [mt2060] [] mt2060_attach+0x40/0x1ea [mt2060] [] dibusb_dib3000mc_tuner_attach+0x126/0x16c [ ... ] (generic USB-layer stacktrace omitted). -- Jiri Kosina From EMAIL_REMOVED Wed Oct 18 18:37:34 2006 Date: Wed, 18 Oct 2006 18:37:34 +0200 (CEST) From: Jiri Kosina To: Jean Delvare Cc: Patrick Boettcher , Mauro Carvalho Chehab , , Subject: [PATCH] 1/2: I2C && DVB: fix recursive locking lockped warning in i2c_transfer() This patch adds the 'level' field into the i2c_adapter structure, which is used to represent the 'logical' level of nesting for the purposes of lockdep. This field is then used in the i2c_transfer() function, to acquire the per-adapter bus_lock with correct nesting level. Signed-off-by: Jiri Kosina --- drivers/i2c/i2c-core.c | 2 +- include/linux/i2c.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 7ca81f4..79eaa12 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -603,7 +603,7 @@ #ifdef DEBUG } #endif - mutex_lock(&adap->bus_lock); + mutex_lock_nested(&adap->bus_lock, adap->level); ret = adap->algo->master_xfer(adap,msgs,num); mutex_unlock(&adap->bus_lock); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 9b5d047..08df416 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -216,6 +216,7 @@ struct i2c_adapter { int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ + u8 level; /* nesting level for lockdep */ struct mutex bus_lock; struct mutex clist_lock; From EMAIL_REMOVED Wed Oct 18 18:37:47 2006 Date: Wed, 18 Oct 2006 18:37:47 +0200 (CEST) From: Jiri Kosina To: Jean Delvare Cc: Patrick Boettcher , Mauro Carvalho Chehab , , Subject: [PATCH] 2/2: I2C && DVB: fix recursive locking lockped warning in i2c_transfer() This patch adds proper setting of 'level' parameter in the DVB layer. Depends on previous patch, adding this field into struct i2c_adapter Signed-off-by: Jiri Kosina --- drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | 2 ++ drivers/media/dvb/frontends/dibx000_common.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 55ba020..ed61a26 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c @@ -27,6 +27,8 @@ #else #endif d->i2c_adap.algo = d->props.i2c_algo; d->i2c_adap.algo_data = NULL; + /* DVB adapter locks after DVB frontend */ + d->i2c_adap.level = 1; i2c_set_adapdata(&d->i2c_adap, d); diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index a18c8f4..6af2a5e 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c @@ -111,6 +111,8 @@ static int i2c_adapter_init(struct i2c_a i2c_adap->class = I2C_CLASS_TV_DIGITAL, i2c_adap->algo = algo; i2c_adap->algo_data = NULL; + /* DVB frontend locks before DVB adapter */ + i2c_adap->level = 0; i2c_set_adapdata(i2c_adap, mst); if (i2c_add_adapter(i2c_adap) < 0) return -ENODEV;