summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbibhayr <bibhayr@nvidia.com>2014-06-11 19:44:01 -0700
committerMandar Padmawar <mpadmawar@nvidia.com>2014-06-25 00:49:21 -0700
commit03594fba1aadc12c1eb79b4d338418768a0d6abb (patch)
treec9d87c6d7c17973503de60e13e06c485fdafdff0
parent3c1272799248f9e9e1660b9eaefd2c3789274647 (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.c57
-rw-r--r--drivers/staging/ozwpan/ozpd.h2
-rw-r--r--drivers/staging/ozwpan/ozproto.c9
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(&current_time);
if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||