firewire: sbp2: protect a reference counter properly
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Mon, 3 Mar 2014 22:22:35 +0000 (23:22 +0100)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Wed, 10 Dec 2014 19:53:20 +0000 (20:53 +0100)
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 <stefanr@s5r6.in-berlin.de>
drivers/firewire/sbp2.c

index 7aef911..c7fc78c 100644 (file)
@@ -689,14 +689,12 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
 
 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);
 }
 
 /*