Hi Brian, > > > > * > > > > @@ -2227,7 +2237,7 @@ static void mwifiex_recreate_adapter(struct > > > sdio_mmc_card *card) > > > > * discovered and initializes them from scratch. > > > > */ > > > > > > > > - mwifiex_sdio_remove(func); > > > > + __mwifiex_sdio_remove(func); > > > > > > ^^ So here, you're trying to avoid syncing with the card-reset work > > > event, except that function will free up all your resources > > > (including the static save_adapter). Thus, you're explicitly > > > allowing a use-after- free error here. That seems unwise. > > > > Even if firmware dump is triggered after card reset is started, it > > will execute after card reset is completed as discussed above. Only > > problem I can see is with "save_adapter". We can put new_adapter > > pointer in "save_adapter" at the end of mwifiex_recreate_adapter() to > > solve the issue. > > Ugh, yet another band-aid? You might do better to still cancel any > pending work, just don't do it synchronously. i.e., do cancel_work() > after you've removed the card. It doesn't make sense to do a FW dump on > the "new" adapter when it was requested for the old one. I could not find async version of cancel_work(). We can fix this problem with below change at the end of mwifiex_sdio_work(). All pending work requests would be ignored. -------- @ -2571,6 +2571,8 @@ static void mwifiex_sdio_work(struct work_struct *work) if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags)) mwifiex_sdio_card_reset_work(save_adapter); + clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); + clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); } ---------- > > > > Instead, you should actually retain the invariant that you're doing > > > a full remove/reinitialize here, which includes doing the *same* > > > cancel_work_sync() here in mwifiex_recreate_adapter() as you would > > > in any other remove(). > > > > We are executing mwifiex_recreate_adapter() as a part of sdio_work(). > > Calling > > cancel_work_sync() here would cause deadlock. The API is supposed to > > waits until sdio_work() is finished. > > You are correct. So using the _sync() version would be wrong. > > > > > > > IOW, kill the __mwifiex_sdio_remove() and just call > > > mwifiex_sdio_remove() as you were. > > > > > > That also means that you can do the same per-adapter cleanup in the > > > following patch as you do for PCIe. > > > > Currently as sdio_work recreates "card", the work structure can't be > moved inside card structure. > > Let me know your suggestions. > > If you address the TODO in mwifiex_create_adapter() instead, you can > get past this problem: > > /* TODO mmc_hw_reset does not require destroying and re-probing > the > * whole adapter. Hence there was no need to for this rube- > goldberg > * design to reload the fw from an external workqueue. If we > don't > * destroy the adapter we could reload the fw from > * mwifiex_main_work_queue directly. > > The "save_adapter" is an abomination that should be terminated swiftly, > but it is perpetuated in part by the hacks noted in the TODO. > > So I'd recommend addressing the TODO ASAP, but in the meantime, a hack > like my suggestion (cancel the FW dump work w/o synchronizing) or -- > less preferably -- yours (manually set 'save_adapter' again) might be > OK. > > I think I've asked elsewhere but didn't receive an answer: why is > SDIO's mwifiex_recreate_adapter() so much different from PCIe's > mwifiex_do_flr()? It seems like the latter should be refactored to > remove some of the PCIe-specific cruft from main.c and then reused for > SDIO. Our initial SDIO card reset implementation was based on MMC APIs where remove() and probe() would automatically get called by MMC subsystem after power cycle. https://www.spinics.net/lists/linux-wireless/msg98435.html Later it was improved by Andreas Fenkart by replacing those power cycle APIs with mmc_hw_reset(). For PCIe, function level reset is standard feature. We implemented ".reset_notify" handler which gets called after and before FLR. You are right. We can have SDIO's handling similar to PCIe and avoid destroying+recreating adapter/card. We have started working on this. We will get rid of global save_adapter, sdio_work etc. Meanwhile I will post above mentioned change if it looks good to you. Regards, Amitkumar