diff options
author | bibhayr <bibhayr@nvidia.com> | 2014-06-11 19:44:01 -0700 |
---|---|---|
committer | Mandar Padmawar <mpadmawar@nvidia.com> | 2014-06-25 00:49:21 -0700 |
commit | 03594fba1aadc12c1eb79b4d338418768a0d6abb (patch) | |
tree | c9d87c6d7c17973503de60e13e06c485fdafdff0 | |
parent | 3c1272799248f9e9e1660b9eaefd2c3789274647 (diff) |
staging: ozwpan: remove scheduling while atomic
Call kobject_uevent_env() from process context.
Bug 1523226
Change-Id: I6b5569f986b179f8b804642dc3702f3a3f10d180
Reviewed-on: http://git-master/r/422536
(cherry picked from commit 3e6733bb4f62148b38af8ccbe56dc0e62a052138)
Signed-off-by: Jean Huang <jeanh@nvidia.com>
Reviewed-on: http://git-master/r/427952
GVS: Gerrit_Virtual_Submit
-rw-r--r-- | drivers/staging/ozwpan/ozpd.c | 57 | ||||
-rw-r--r-- | drivers/staging/ozwpan/ozpd.h | 2 | ||||
-rw-r--r-- | drivers/staging/ozwpan/ozproto.c | 9 |
3 files changed, 48 insertions, 20 deletions
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index ad4acb59e8d9..02bd478e9eed 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -258,16 +258,55 @@ static void oz_pd_free(struct work_struct *work) */ 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 (in_softirq()) { + /* We are in softirq context, + * Should use work_queue to call free() in process context + */ + int ret; + memset(&pd->workitem, 0, sizeof(pd->workitem)); + INIT_WORK(&pd->workitem, oz_pd_free); + ret = schedule_work(&pd->workitem); + if (ret) + oz_trace("failed to schedule workitem\n"); + } else { + /* We are in process context. + * Call oz_pd_free() immediately. + */ + oz_pd_free(&pd->workitem); + } +} +/*------------------------------------------------------------------------------ + */ +static void oz_pd_uevent_workitem(struct work_struct *work) +{ + struct oz_pd *pd; + char mac_buf[20]; + char *envp[2]; + + pd = container_of(work, struct oz_pd, uevent_workitem); + + oz_trace_msg(D, "uevent ID_MAC:%pm\n", pd->mac_addr); + snprintf(mac_buf, sizeof(mac_buf), "ID_MAC=%pm", pd->mac_addr); + envp[0] = mac_buf; + envp[1] = NULL; + kobject_uevent_env(&g_oz_wpan_dev->kobj, KOBJ_CHANGE, envp); + oz_pd_put(pd); +} +/*------------------------------------------------------------------------------ + */ +void oz_pd_notify_uevent(struct oz_pd *pd) +{ + int ret; + + oz_pd_get(pd); + memset(&pd->uevent_workitem, 0, sizeof(pd->uevent_workitem)); + INIT_WORK(&pd->uevent_workitem, oz_pd_uevent_workitem); + ret = schedule_work(&pd->uevent_workitem); if (ret) oz_trace("failed to schedule workitem\n"); @@ -374,12 +413,6 @@ int oz_pd_sleep(struct oz_pd *pd) { int do_stop = 0; u16 stop_apps = 0; - char mac_buf[20]; - char *envp[2]; - - snprintf(mac_buf, sizeof(mac_buf), "ID_MAC=%pm", pd->mac_addr); - envp[0] = mac_buf; - envp[1] = NULL; oz_polling_lock_bh(); if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { oz_polling_unlock_bh(); @@ -389,7 +422,7 @@ int oz_pd_sleep(struct oz_pd *pd) if (pd->keep_alive >= OZ_KALIVE_INFINITE) oz_pd_indicate_farewells(pd); oz_pd_set_state(pd, OZ_PD_S_SLEEP); - kobject_uevent_env(&g_oz_wpan_dev->kobj, KOBJ_CHANGE, envp); + oz_pd_notify_uevent(pd); } else { do_stop = 1; } diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h index a4270fe69ee5..5f5e7241ff47 100644 --- a/drivers/staging/ozwpan/ozpd.h +++ b/drivers/staging/ozwpan/ozpd.h @@ -109,6 +109,7 @@ struct oz_pd { struct tasklet_struct timeout_tasklet; unsigned long tasklet_sched; struct work_struct workitem; + struct work_struct uevent_workitem; u8 up_audio_buf; }; @@ -134,5 +135,6 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len); void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt); void oz_apps_init(void); void oz_apps_term(void); +void oz_pd_notify_uevent(struct oz_pd *pd); #endif /* Sentry */ diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 1066c4e49ad7..a9eea6e0692d 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -352,15 +352,8 @@ static void oz_rx_frame(struct sk_buff *skb) pd = oz_pd_find(src_addr); if (pd) { if (!(pd->state & OZ_PD_S_CONNECTED)) { - char mac_buf[20]; - char *envp[2]; - snprintf(mac_buf, sizeof(mac_buf), "ID_MAC=%pm", - pd->mac_addr); - envp[0] = mac_buf; - envp[1] = NULL; oz_pd_set_state(pd, OZ_PD_S_CONNECTED); - kobject_uevent_env(&g_oz_wpan_dev->kobj, KOBJ_CHANGE, - envp); + oz_pd_notify_uevent(pd); } getnstimeofday(¤t_time); if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || |