> > However, the interface iterator will simply not run at all if ->stop has > > already succeeded since no interfaces would be UP, so you don't really > > have to protect it against that, you only have to make sure it's not > > running when you unregister your hardware struct, and _that_ doesn't > > have the rtnl taken so you can use cancel_work_sync() there. > > True, but the race condition happens when ieee80211_stop() is called, > and the rt2x00 work is triggered before before > rt2x00->remove_interface() or rt2x00>stop() is called. when stop() is > then called it cannot use cancel_work_sync() because > the work structure is waiting until stop() has completed which will > not end until cancel_work_sync() has completed. No, but I'm saying that ->stop doesn't need to cancel_work_sync(). You should have a work struct that you exclusively use for whatever you need to do with interfaces, so the code looks something like this: void work(...) { iterate_interfaces(); } maybe with some additional locking. You also use schedule_work() and not the mac80211-provided workqueue. This work will do exactly nothing if triggered before ->stop and running after ->stop because all interfaces will be gone. Hence, you don't need to cancel it in ->stop, you don't care whether it'll run or not. Hence, the only thing you need to take care of is that it's canceled before unregister_hw(), and for that you can use cancel_work_sync(). Am I missing something? johannes
Attachment:
signature.asc
Description: This is a digitally signed message part