[PATCH 12/24] staging: wilc1000: move static variable 'terminated_handle' to wilc_vif struct
Ajay Singh
ajay.kathat at microchip.com
Mon Aug 27 05:27:31 UTC 2018
On Fri, 24 Aug 2018 11:46:39 +0300
Claudiu Beznea <Claudiu.Beznea at microchip.com> wrote:
> On 23.08.2018 17:36, Ajay Singh wrote:
> > On Thu, 23 Aug 2018 11:11:18 +0300
> > Claudiu Beznea <Claudiu.Beznea at microchip.com> wrote:
> >
> >> On 14.08.2018 09:50, Ajay Singh wrote:
> >>> Remove the use of static variable 'terminated_handle' and instead
> >>> move in wilc_vif struct.
> >>> After moving this variable to wilc_vif struct its not required to
> >>> keep 'terminated_handle', so changed it to boolean type.
> >>
> >> You can remove it at all and use wilc->hif_deinit_lock mutex also
> >> in wilc_scan_complete_received() and wilc_network_info_received()
> >> it is used in wilc_gnrl_async_info_received().
> >
> > In my understanding, 'terminated_handle' is used to know the
> > status when interface is getting deinit(). During deinitialization
> > of an interface if any async event received for the interface(from
> > firmware) should be ignored.
>
> 'terminated_handle' true only inside mutex. So, outside of it it will
> be false, so *mostly* it will tell you when mutex is locked for
> deinit. *Mostly*, because context switches may happen while a mutex
> is locked.
>
Yes, outside the mutex 'terminated_handle' would be false.
I already agreed that while fixing the bug using 'terminated_handle'
all the scenarios are not handled but as you suggested before
to remove 'terminated_handle' and only use 'mutex' will also not
help to address all corner scenarios. So, I suggest to keep the
current status by making use of this flag and handle all scenario in
later patch to de-initialization graceful.
> With the current approach you have this code:
>
> int wilc_deinit(struct wilc_vif *vif)
> {
> // ...
> mutex_lock(&vif->wilc->hif_deinit_lock);
>
> // (A)
>
> vif->is_termination_progress = true;
> // ...
> vif->is_termination_progress = false;
>
> mutex_unlokc(&vif->wilc->hif_deinit_lock);
> }
>
> And:
>
> void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32
> length) {
> // ...
> if (!hif_drv || vif->is_termination_progress) {
> netdev_err(vif->ndev, "driver not init[%p]\n",
> hif_drv); return;
> }
>
> // ...
>
> // (B)
> result = wilc_enqueue_work(msg);
> // ...
> }
>
> And:
>
> static int wilc_enqueue_work(struct host_if_msg *msg)
>
> {
>
> INIT_WORK(&msg->work, msg->fn);
>
>
>
> if (!msg->vif || !msg->vif->wilc
> || !msg->vif->wilc->hif_workqueue)
>
> return -EINVAL;
>
>
> // (C)
> if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
>
> return -EINVAL;
>
>
>
> return 0;
>
> }
>
>
> You may have the following scenario:
> 1. context switch in wilc_deinit() just after the mutex is taken
> (point A above). vif->is_termination_progress = false at this point.
>
> 2. a new packet is received and wilc_network_info_received() gets
> executed and execution reaches point B, goes to wilc_enqueue_work()
> and suspend at point C then context switch.
>
Thanks for explaining the scenario with an example.
For the given scenario, I think not only here it can even suspend
after posting the work queue and start the execution of handler
function eg. handle_recvd_gnrl_async_info()(there is no protection in
handle function)
There are some combination of these scenario, I will relook into these
cases and check how to handle them separately.
> 3. wilc_deinit() resumes and finish its execution.
>
> 4. wilc_enqueue_work() resumes and queue_work() is executed but you
> already freed the hif_workqueue. You will have a crash here.
>
> Notice that hif_drv is not set to NULL on wilc_deinit() after it is
> kfree().
>
> >
> > In my opinion its not right to only wait for the mutex in any of
> > callback e.g wilc_scan_complete_received() because it will delay the
> > handling of callback and try to process the event once lock is
> > available for the interface which is already de-initialized.
>
> But this is already done for wilc_gnrl_async_info_received().
>
> >
> > Based on my understand 'mutex' alone is not enough to
> > handle this and we some extra check to know if interface is down.
>
> terminated_handle will *mostly* tell you when the mutex is locked,
> nothing more.
>
> I will
> > check more about this patch how to handle the extra scenario for
> > this case.
> > Please suggest if someone has better idea on how to handle this.
> >
More information about the devel
mailing list