From: Rupesh Gujare Date: Thu, 22 Aug 2013 16:38:51 +0000 (+0100) Subject: staging: ozwpan: Create deferred work to destroy PD object. X-Git-Tag: firefly_0821_release~176^2~5471^2~169 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6af47622398d65e4cb3a52af5de52c6b447270d5;p=firefly-linux-kernel-4.4.55.git staging: ozwpan: Create deferred work to destroy PD object. Currently we call oz_pd_destroy() from softirq context, where we try to destroy relevant data structures, as well we kill a tasklet which always result in following kernel warning. [12279.262194] Attempt to kill tasklet from interrupt [12279.262202] Attempt to kill tasklet from interrupt This patch defers deallocation of data structures to work queue. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index 2514d79a8ff4..06004c8b85fe 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -204,18 +204,16 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr) /*------------------------------------------------------------------------------ * Context: softirq or process */ -void oz_pd_destroy(struct oz_pd *pd) +void oz_pd_free(struct work_struct *work) { struct list_head *e; struct oz_tx_frame *f; struct oz_isoc_stream *st; struct oz_farewell *fwell; + struct oz_pd *pd; oz_pd_dbg(pd, ON, "Destroying PD\n"); - if (hrtimer_active(&pd->timeout)) - hrtimer_cancel(&pd->timeout); - if (hrtimer_active(&pd->heartbeat)) - hrtimer_cancel(&pd->heartbeat); + pd = container_of(work, struct oz_pd, workitem); /*Disable timer tasklets*/ tasklet_kill(&pd->heartbeat_tasklet); tasklet_kill(&pd->timeout_tasklet); @@ -258,6 +256,26 @@ void oz_pd_destroy(struct oz_pd *pd) kfree(pd); } +/*------------------------------------------------------------------------------ + * Context: softirq or Process + */ +void oz_pd_destroy(struct oz_pd *pd) +{ + int ret; + + if (hrtimer_active(&pd->timeout)) + hrtimer_cancel(&pd->timeout); + if (hrtimer_active(&pd->heartbeat)) + hrtimer_cancel(&pd->heartbeat); + + memset(&pd->workitem, 0, sizeof(pd->workitem)); + INIT_WORK(&pd->workitem, oz_pd_free); + ret = schedule_work(&pd->workitem); + + if (ret) + oz_pd_dbg(pd, ON, "failed to schedule workitem\n"); +} + /*------------------------------------------------------------------------------ * Context: softirq-serialized */ diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h index 996ef65ed315..12c712956888 100644 --- a/drivers/staging/ozwpan/ozpd.h +++ b/drivers/staging/ozwpan/ozpd.h @@ -99,6 +99,7 @@ struct oz_pd { u8 timeout_type; struct tasklet_struct heartbeat_tasklet; struct tasklet_struct timeout_tasklet; + struct work_struct workitem; }; #define OZ_MAX_QUEUED_FRAMES 4