]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
staging: ozwpan: flush workqueue
authorVinayak Pane <vpane@nvidia.com>
Mon, 30 Jun 2014 07:41:10 +0000 (00:41 -0700)
committerPradeep Thiruchelvam <pradeept@nvidia.com>
Tue, 1 Jul 2014 22:24:23 +0000 (15:24 -0700)
uevent workqueue needs to be flushed before pd free.
destroy workqueue should not have been rescheduled.

Don't make work struct NULL again.

Bug 200016744

Change-Id: Ief24aad7d787ca3ce6f0c5b4f41656aa50bf2bf4
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/432633
Reviewed-by: Allen Yu <alleny@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
drivers/staging/ozwpan/ozpd.c

index 27e06be53b4f4bbc8645f0245c25e733a58a0b6c..0872c76586e49c389c598f48a3fa1a739f257d69 100644 (file)
@@ -40,6 +40,7 @@ static int oz_def_app_start(struct oz_pd *pd, int resume);
 static void oz_def_app_stop(struct oz_pd *pd, int pause);
 static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt);
 static void oz_pd_free(struct work_struct *work);
+static void oz_pd_uevent_workitem(struct work_struct *work);
 /*------------------------------------------------------------------------------
  * Counts the uncompleted isoc frames submitted to netcard.
  */
@@ -204,8 +205,8 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
 
                spin_lock_init(&pd->pd_destroy_lock);
                pd->pd_destroy_scheduled = false;
-               memset(&pd->workitem, 0, sizeof(pd->workitem));
                INIT_WORK(&pd->workitem, oz_pd_free);
+               INIT_WORK(&pd->uevent_workitem, oz_pd_uevent_workitem);
        }
        return pd;
 }
@@ -220,6 +221,12 @@ static void oz_pd_free(struct work_struct *work)
        oz_trace_msg(M, "Destroying PD:%p\n", pd);
        tasklet_kill(&pd->heartbeat_tasklet);
        tasklet_kill(&pd->timeout_tasklet);
+
+       /* Finish scheduled uevent work, uevent might be rescheduled by
+        * oz timeout tasklet again
+        */
+       cancel_work_sync(&pd->uevent_workitem);
+
        /* Delete any streams.
         */
        e = pd->stream_list.next;
@@ -258,6 +265,7 @@ static void oz_pd_free(struct work_struct *work)
                oz_trace_msg(M, "dev_put(%p)\n", pd->net_dev);
                dev_put(pd->net_dev);
        }
+
        kfree(pd);
 }
 
@@ -284,6 +292,7 @@ void oz_pd_destroy(struct oz_pd *pd)
        if (hrtimer_active(&pd->heartbeat))
                hrtimer_cancel(&pd->heartbeat);
 
+
        ret = schedule_work(&pd->workitem);
        if (!ret)
                pr_info("failed to schedule workitem\n");
@@ -313,12 +322,10 @@ 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);
 
+       ret = schedule_work(&pd->uevent_workitem);
        if (!ret) {
-               oz_trace("failed to schedule workitem\n");
+               pr_info("%s: failed to schedule workitem\n", __func__);
                oz_pd_put(pd);
        }
 }