Date: Mon, 3 Mar 2014 23:22:35 +0100 From: Stefan Richter Subject: firewire: sbp2: protect a reference counter properly The assertion in the comment in sbp2_allow_block() is no longer true. Or maybe it never was true. At least now, the sole caller of sbp2_allow_block(), sbp2_login, can run concurrently to one of sbp2_unblock()'s callers, sbp2_remove. sbp2_login is performed by sbp2_logical_unit.work. sbp2_remove is performed by fw_device.work. sbp2_remove cancels sbp2_logical_unit.work, but only after it called sbp2_unblock. Signed-off-by: Stefan Richter --- drivers/firewire/sbp2.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -689,14 +689,12 @@ static void sbp2_agent_reset_no_wait(str static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) { - /* - * We may access dont_block without taking card->lock here: - * All callers of sbp2_allow_block() and all callers of sbp2_unblock() - * are currently serialized against each other. - * And a wrong result in sbp2_conditionally_block()'s access of - * dont_block is rather harmless, it simply misses its first chance. - */ - --lu->tgt->dont_block; + struct sbp2_target *tgt = lu->tgt; + struct fw_card *card = target_parent_device(tgt)->card; + + spin_lock_irq(&card->lock); + --tgt->dont_block; + spin_unlock_irq(&card->lock); } /*