staging: unisys: move periodic_work.c into the visorbus directory
authorErik Arfvidson <erik.arfvidson@unisys.com>
Tue, 5 May 2015 22:37:07 +0000 (18:37 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 May 2015 13:27:32 +0000 (15:27 +0200)
This patch removes visorutil directory, move periodic_work.c into
the visorbus directory.

Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com>
Signed-off-by: Benjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/unisys/Kconfig
drivers/staging/unisys/visorbus/Makefile
drivers/staging/unisys/visorbus/periodic_work.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/Kconfig [deleted file]
drivers/staging/unisys/visorutil/Makefile [deleted file]
drivers/staging/unisys/visorutil/periodic_work.c [deleted file]

index e0562f1336137523fb47b2b13b5ec0d30dec929e..0c3e9a1368a87294e1d7ddce4d30723f8d389bf4 100644 (file)
@@ -11,7 +11,6 @@ menuconfig UNISYSSPAR
 
 if UNISYSSPAR
 
-source "drivers/staging/unisys/visorutil/Kconfig"
 source "drivers/staging/unisys/visorbus/Kconfig"
 
 endif # UNISYSSPAR
index 16d3ff507a0ad265654fcb958b524a3d209c6f88..72d4d4429684ac77c10909e0b4753983469f9542 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_UNISYS_VISORBUS)   += visorbus.o
 visorbus-y := visorbus_main.o
 visorbus-y += visorchannel.o
 visorbus-y += visorchipset.o
+visorbus-y += periodic_work.o
 
 ccflags-y += -Idrivers/staging/unisys/include
 ccflags-y += -Idrivers/staging/unisys/common-spar/include
diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c
new file mode 100644 (file)
index 0000000..3562e8b
--- /dev/null
@@ -0,0 +1,205 @@
+/* periodic_work.c
+ *
+ * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Helper functions to schedule periodic work in Linux kernel mode.
+ */
+#include <linux/sched.h>
+
+#include "periodic_work.h"
+
+#define MYDRVNAME "periodic_work"
+
+struct periodic_work {
+       rwlock_t lock;
+       struct delayed_work work;
+       void (*workfunc)(void *);
+       void *workfuncarg;
+       bool is_scheduled;
+       bool want_to_stop;
+       ulong jiffy_interval;
+       struct workqueue_struct *workqueue;
+       const char *devnam;
+};
+
+static void periodic_work_func(struct work_struct *work)
+{
+       struct periodic_work *pw;
+
+       pw = container_of(work, struct periodic_work, work.work);
+       (*pw->workfunc)(pw->workfuncarg);
+}
+
+struct periodic_work *visor_periodic_work_create(ulong jiffy_interval,
+                                       struct workqueue_struct *workqueue,
+                                       void (*workfunc)(void *),
+                                       void *workfuncarg,
+                                       const char *devnam)
+{
+       struct periodic_work *pw;
+
+       pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY);
+       if (!pw)
+               return NULL;
+
+       rwlock_init(&pw->lock);
+       pw->jiffy_interval = jiffy_interval;
+       pw->workqueue = workqueue;
+       pw->workfunc = workfunc;
+       pw->workfuncarg = workfuncarg;
+       pw->devnam = devnam;
+       return pw;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_create);
+
+void visor_periodic_work_destroy(struct periodic_work *pw)
+{
+       kfree(pw);
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_destroy);
+
+/** Call this from your periodic work worker function to schedule the next
+ *  call.
+ *  If this function returns false, there was a failure and the
+ *  periodic work is no longer scheduled
+ */
+bool visor_periodic_work_nextperiod(struct periodic_work *pw)
+{
+       bool rc = false;
+
+       write_lock(&pw->lock);
+       if (pw->want_to_stop) {
+               pw->is_scheduled = false;
+               pw->want_to_stop = false;
+               rc = true;  /* yes, true; see visor_periodic_work_stop() */
+               goto unlock;
+       } else if (queue_delayed_work(pw->workqueue, &pw->work,
+                                     pw->jiffy_interval) < 0) {
+               pw->is_scheduled = false;
+               rc = false;
+               goto unlock;
+       }
+       rc = true;
+unlock:
+       write_unlock(&pw->lock);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_nextperiod);
+
+/** This function returns true iff new periodic work was actually started.
+ *  If this function returns false, then no work was started
+ *  (either because it was already started, or because of a failure).
+ */
+bool visor_periodic_work_start(struct periodic_work *pw)
+{
+       bool rc = false;
+
+       write_lock(&pw->lock);
+       if (pw->is_scheduled) {
+               rc = false;
+               goto unlock;
+       }
+       if (pw->want_to_stop) {
+               rc = false;
+               goto unlock;
+       }
+       INIT_DELAYED_WORK(&pw->work, &periodic_work_func);
+       if (queue_delayed_work(pw->workqueue, &pw->work,
+                              pw->jiffy_interval) < 0) {
+               rc = false;
+               goto unlock;
+       }
+       pw->is_scheduled = true;
+       rc = true;
+unlock:
+       write_unlock(&pw->lock);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_start);
+
+/** This function returns true iff your call actually stopped the periodic
+ *  work.
+ *
+ *  -- PAY ATTENTION... this is important --
+ *
+ *  NO NO #1
+ *
+ *     Do NOT call this function from some function that is running on the
+ *     same workqueue as the work you are trying to stop might be running
+ *     on!  If you violate this rule, visor_periodic_work_stop() MIGHT work,
+ *     but it also MIGHT get hung up in an infinite loop saying
+ *     "waiting for delayed work...".  This will happen if the delayed work
+ *     you are trying to cancel has been put in the workqueue list, but can't
+ *     run yet because we are running that same workqueue thread right now.
+ *
+ *     Bottom line: If you need to call visor_periodic_work_stop() from a
+ *     workitem, be sure the workitem is on a DIFFERENT workqueue than the
+ *     workitem that you are trying to cancel.
+ *
+ *     If I could figure out some way to check for this "no no" condition in
+ *     the code, I would.  It would have saved me the trouble of writing this
+ *     long comment.  And also, don't think this is some "theoretical" race
+ *     condition.  It is REAL, as I have spent the day chasing it.
+ *
+ *  NO NO #2
+ *
+ *     Take close note of the locks that you own when you call this function.
+ *     You must NOT own any locks that are needed by the periodic work
+ *     function that is currently installed.  If you DO, a deadlock may result,
+ *     because stopping the periodic work often involves waiting for the last
+ *     iteration of the periodic work function to complete.  Again, if you hit
+ *     this deadlock, you will get hung up in an infinite loop saying
+ *     "waiting for delayed work...".
+ */
+bool visor_periodic_work_stop(struct periodic_work *pw)
+{
+       bool stopped_something = false;
+
+       write_lock(&pw->lock);
+       stopped_something = pw->is_scheduled && (!pw->want_to_stop);
+       while (pw->is_scheduled) {
+               pw->want_to_stop = true;
+               if (cancel_delayed_work(&pw->work)) {
+                       /* We get here if the delayed work was pending as
+                        * delayed work, but was NOT run.
+                        */
+                       WARN_ON(!pw->is_scheduled);
+                       pw->is_scheduled = false;
+               } else {
+                       /* If we get here, either the delayed work:
+                        * - was run, OR,
+                        * - is running RIGHT NOW on another processor, OR,
+                        * - wasn't even scheduled (there is a miniscule
+                        *   timing window where this could be the case)
+                        * flush_workqueue() would make sure it is finished
+                        * executing, but that still isn't very useful, which
+                        * explains the loop...
+                        */
+               }
+               if (pw->is_scheduled) {
+                       write_unlock(&pw->lock);
+                       __set_current_state(TASK_INTERRUPTIBLE);
+                       schedule_timeout(10);
+                       write_lock(&pw->lock);
+               } else {
+                       pw->want_to_stop = false;
+               }
+       }
+       write_unlock(&pw->lock);
+       return stopped_something;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_stop);
diff --git a/drivers/staging/unisys/visorutil/Kconfig b/drivers/staging/unisys/visorutil/Kconfig
deleted file mode 100644 (file)
index be9c2cf..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Unisys timskmod configuration
-#
-
-config UNISYS_VISORUTIL
-       tristate "Unisys visorutil driver"
-       ---help---
-       If you say Y here, you will enable the Unisys visorutil driver.
-
diff --git a/drivers/staging/unisys/visorutil/Makefile b/drivers/staging/unisys/visorutil/Makefile
deleted file mode 100644 (file)
index 8f6a3e3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for Unisys timskmod
-#
-
-obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o
-
-visorutil-y := periodic_work.o
-
-ccflags-y += -Idrivers/staging/unisys/include
diff --git a/drivers/staging/unisys/visorutil/periodic_work.c b/drivers/staging/unisys/visorutil/periodic_work.c
deleted file mode 100644 (file)
index 3562e8b..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/* periodic_work.c
- *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/*
- *  Helper functions to schedule periodic work in Linux kernel mode.
- */
-#include <linux/sched.h>
-
-#include "periodic_work.h"
-
-#define MYDRVNAME "periodic_work"
-
-struct periodic_work {
-       rwlock_t lock;
-       struct delayed_work work;
-       void (*workfunc)(void *);
-       void *workfuncarg;
-       bool is_scheduled;
-       bool want_to_stop;
-       ulong jiffy_interval;
-       struct workqueue_struct *workqueue;
-       const char *devnam;
-};
-
-static void periodic_work_func(struct work_struct *work)
-{
-       struct periodic_work *pw;
-
-       pw = container_of(work, struct periodic_work, work.work);
-       (*pw->workfunc)(pw->workfuncarg);
-}
-
-struct periodic_work *visor_periodic_work_create(ulong jiffy_interval,
-                                       struct workqueue_struct *workqueue,
-                                       void (*workfunc)(void *),
-                                       void *workfuncarg,
-                                       const char *devnam)
-{
-       struct periodic_work *pw;
-
-       pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY);
-       if (!pw)
-               return NULL;
-
-       rwlock_init(&pw->lock);
-       pw->jiffy_interval = jiffy_interval;
-       pw->workqueue = workqueue;
-       pw->workfunc = workfunc;
-       pw->workfuncarg = workfuncarg;
-       pw->devnam = devnam;
-       return pw;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_create);
-
-void visor_periodic_work_destroy(struct periodic_work *pw)
-{
-       kfree(pw);
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_destroy);
-
-/** Call this from your periodic work worker function to schedule the next
- *  call.
- *  If this function returns false, there was a failure and the
- *  periodic work is no longer scheduled
- */
-bool visor_periodic_work_nextperiod(struct periodic_work *pw)
-{
-       bool rc = false;
-
-       write_lock(&pw->lock);
-       if (pw->want_to_stop) {
-               pw->is_scheduled = false;
-               pw->want_to_stop = false;
-               rc = true;  /* yes, true; see visor_periodic_work_stop() */
-               goto unlock;
-       } else if (queue_delayed_work(pw->workqueue, &pw->work,
-                                     pw->jiffy_interval) < 0) {
-               pw->is_scheduled = false;
-               rc = false;
-               goto unlock;
-       }
-       rc = true;
-unlock:
-       write_unlock(&pw->lock);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_nextperiod);
-
-/** This function returns true iff new periodic work was actually started.
- *  If this function returns false, then no work was started
- *  (either because it was already started, or because of a failure).
- */
-bool visor_periodic_work_start(struct periodic_work *pw)
-{
-       bool rc = false;
-
-       write_lock(&pw->lock);
-       if (pw->is_scheduled) {
-               rc = false;
-               goto unlock;
-       }
-       if (pw->want_to_stop) {
-               rc = false;
-               goto unlock;
-       }
-       INIT_DELAYED_WORK(&pw->work, &periodic_work_func);
-       if (queue_delayed_work(pw->workqueue, &pw->work,
-                              pw->jiffy_interval) < 0) {
-               rc = false;
-               goto unlock;
-       }
-       pw->is_scheduled = true;
-       rc = true;
-unlock:
-       write_unlock(&pw->lock);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_start);
-
-/** This function returns true iff your call actually stopped the periodic
- *  work.
- *
- *  -- PAY ATTENTION... this is important --
- *
- *  NO NO #1
- *
- *     Do NOT call this function from some function that is running on the
- *     same workqueue as the work you are trying to stop might be running
- *     on!  If you violate this rule, visor_periodic_work_stop() MIGHT work,
- *     but it also MIGHT get hung up in an infinite loop saying
- *     "waiting for delayed work...".  This will happen if the delayed work
- *     you are trying to cancel has been put in the workqueue list, but can't
- *     run yet because we are running that same workqueue thread right now.
- *
- *     Bottom line: If you need to call visor_periodic_work_stop() from a
- *     workitem, be sure the workitem is on a DIFFERENT workqueue than the
- *     workitem that you are trying to cancel.
- *
- *     If I could figure out some way to check for this "no no" condition in
- *     the code, I would.  It would have saved me the trouble of writing this
- *     long comment.  And also, don't think this is some "theoretical" race
- *     condition.  It is REAL, as I have spent the day chasing it.
- *
- *  NO NO #2
- *
- *     Take close note of the locks that you own when you call this function.
- *     You must NOT own any locks that are needed by the periodic work
- *     function that is currently installed.  If you DO, a deadlock may result,
- *     because stopping the periodic work often involves waiting for the last
- *     iteration of the periodic work function to complete.  Again, if you hit
- *     this deadlock, you will get hung up in an infinite loop saying
- *     "waiting for delayed work...".
- */
-bool visor_periodic_work_stop(struct periodic_work *pw)
-{
-       bool stopped_something = false;
-
-       write_lock(&pw->lock);
-       stopped_something = pw->is_scheduled && (!pw->want_to_stop);
-       while (pw->is_scheduled) {
-               pw->want_to_stop = true;
-               if (cancel_delayed_work(&pw->work)) {
-                       /* We get here if the delayed work was pending as
-                        * delayed work, but was NOT run.
-                        */
-                       WARN_ON(!pw->is_scheduled);
-                       pw->is_scheduled = false;
-               } else {
-                       /* If we get here, either the delayed work:
-                        * - was run, OR,
-                        * - is running RIGHT NOW on another processor, OR,
-                        * - wasn't even scheduled (there is a miniscule
-                        *   timing window where this could be the case)
-                        * flush_workqueue() would make sure it is finished
-                        * executing, but that still isn't very useful, which
-                        * explains the loop...
-                        */
-               }
-               if (pw->is_scheduled) {
-                       write_unlock(&pw->lock);
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(10);
-                       write_lock(&pw->lock);
-               } else {
-                       pw->want_to_stop = false;
-               }
-       }
-       write_unlock(&pw->lock);
-       return stopped_something;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_stop);