kernel: remove linux 3.3 patches and config
[openwrt/svn-archive/archive.git] / target / linux / generic / patches-3.3 / 047-spi_message_queue.patch
diff --git a/target/linux/generic/patches-3.3/047-spi_message_queue.patch b/target/linux/generic/patches-3.3/047-spi_message_queue.patch
deleted file mode 100644 (file)
index 9aff0be..0000000
+++ /dev/null
@@ -1,603 +0,0 @@
-commit ffbbdd21329f3e15eeca6df2d4bc11c04d9d91c0
-Author: Linus Walleij <linus.walleij@linaro.org>
-Date:   Wed Feb 22 10:05:38 2012 +0100
-
-    spi: create a message queueing infrastructure
-    
-    This rips the message queue in the PL022 driver out and pushes
-    it into (optional) common infrastructure. Drivers that want to
-    use the message pumping thread will need to define the new
-    per-messags transfer methods and leave the deprecated transfer()
-    method as NULL.
-    
-    Most of the design is described in the documentation changes that
-    are included in this patch.
-    
-    Since there is a queue that need to be stopped when the system
-    is suspending/resuming, two new calls are implemented for the
-    device drivers to call in their suspend()/resume() functions:
-    spi_master_suspend() and spi_master_resume().
-    
-    ChangeLog v1->v2:
-    - Remove Kconfig entry and do not make the queue support optional
-      at all, instead be more agressive and have it as part of the
-      compulsory infrastructure.
-    - If the .transfer() method is implemented, delete print a small
-      deprecation notice and do not start the transfer pump.
-    - Fix a bitrotted comment.
-    ChangeLog v2->v3:
-    - Fix up a problematic sequence courtesy of Chris Blair.
-    - Stop rather than destroy the queue on suspend() courtesy of
-      Chris Blair.
-    
-    Signed-off-by: Chris Blair <chris.blair@stericsson.com>
-    Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-    Tested-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-    Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-    Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-
-[Florian: dropped the changes on drivers/spi/spi-pl022.c, removed
-the dev_info() about unqueued drivers still using the master function]
-
---- a/Documentation/spi/spi-summary
-+++ b/Documentation/spi/spi-summary
-@@ -1,7 +1,7 @@
- Overview of Linux kernel SPI support
- ====================================
--21-May-2007
-+02-Feb-2012
- What is SPI?
- ------------
-@@ -483,9 +483,9 @@ also initialize its own internal state.
- and those methods.)
- After you initialize the spi_master, then use spi_register_master() to
--publish it to the rest of the system.  At that time, device nodes for
--the controller and any predeclared spi devices will be made available,
--and the driver model core will take care of binding them to drivers.
-+publish it to the rest of the system. At that time, device nodes for the
-+controller and any predeclared spi devices will be made available, and
-+the driver model core will take care of binding them to drivers.
- If you need to remove your SPI controller driver, spi_unregister_master()
- will reverse the effect of spi_register_master().
-@@ -521,21 +521,53 @@ SPI MASTER METHODS
-               ** When you code setup(), ASSUME that the controller
-               ** is actively processing transfers for another device.
--    master->transfer(struct spi_device *spi, struct spi_message *message)
--      This must not sleep.  Its responsibility is arrange that the
--      transfer happens and its complete() callback is issued.  The two
--      will normally happen later, after other transfers complete, and
--      if the controller is idle it will need to be kickstarted.
--
-     master->cleanup(struct spi_device *spi)
-       Your controller driver may use spi_device.controller_state to hold
-       state it dynamically associates with that device.  If you do that,
-       be sure to provide the cleanup() method to free that state.
-+    master->prepare_transfer_hardware(struct spi_master *master)
-+      This will be called by the queue mechanism to signal to the driver
-+      that a message is coming in soon, so the subsystem requests the
-+      driver to prepare the transfer hardware by issuing this call.
-+      This may sleep.
-+
-+    master->unprepare_transfer_hardware(struct spi_master *master)
-+      This will be called by the queue mechanism to signal to the driver
-+      that there are no more messages pending in the queue and it may
-+      relax the hardware (e.g. by power management calls). This may sleep.
-+
-+    master->transfer_one_message(struct spi_master *master,
-+                               struct spi_message *mesg)
-+      The subsystem calls the driver to transfer a single message while
-+      queuing transfers that arrive in the meantime. When the driver is
-+      finished with this message, it must call
-+      spi_finalize_current_message() so the subsystem can issue the next
-+      transfer. This may sleep.
-+
-+    DEPRECATED METHODS
-+
-+    master->transfer(struct spi_device *spi, struct spi_message *message)
-+      This must not sleep. Its responsibility is arrange that the
-+      transfer happens and its complete() callback is issued. The two
-+      will normally happen later, after other transfers complete, and
-+      if the controller is idle it will need to be kickstarted. This
-+      method is not used on queued controllers and must be NULL if
-+      transfer_one_message() and (un)prepare_transfer_hardware() are
-+      implemented.
-+
- SPI MESSAGE QUEUE
--The bulk of the driver will be managing the I/O queue fed by transfer().
-+If you are happy with the standard queueing mechanism provided by the
-+SPI subsystem, just implement the queued methods specified above. Using
-+the message queue has the upside of centralizing a lot of code and
-+providing pure process-context execution of methods. The message queue
-+can also be elevated to realtime priority on high-priority SPI traffic.
-+
-+Unless the queueing mechanism in the SPI subsystem is selected, the bulk
-+of the driver will be managing the I/O queue fed by the now deprecated
-+function transfer().
- That queue could be purely conceptual.  For example, a driver used only
- for low-frequency sensor access might be fine using synchronous PIO.
-@@ -561,4 +593,6 @@ Stephen Street
- Mark Underwood
- Andrew Victor
- Vitaly Wool
--
-+Grant Likely
-+Mark Brown
-+Linus Walleij
---- a/drivers/spi/spi.c
-+++ b/drivers/spi/spi.c
-@@ -30,6 +30,9 @@
- #include <linux/of_spi.h>
- #include <linux/pm_runtime.h>
- #include <linux/export.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/kthread.h>
- static void spidev_release(struct device *dev)
- {
-@@ -507,6 +510,293 @@ spi_register_board_info(struct spi_board
- /*-------------------------------------------------------------------------*/
-+/**
-+ * spi_pump_messages - kthread work function which processes spi message queue
-+ * @work: pointer to kthread work struct contained in the master struct
-+ *
-+ * This function checks if there is any spi message in the queue that
-+ * needs processing and if so call out to the driver to initialize hardware
-+ * and transfer each message.
-+ *
-+ */
-+static void spi_pump_messages(struct kthread_work *work)
-+{
-+      struct spi_master *master =
-+              container_of(work, struct spi_master, pump_messages);
-+      unsigned long flags;
-+      bool was_busy = false;
-+      int ret;
-+
-+      /* Lock queue and check for queue work */
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+      if (list_empty(&master->queue) || !master->running) {
-+              if (master->busy) {
-+                      ret = master->unprepare_transfer_hardware(master);
-+                      if (ret) {
-+                              dev_err(&master->dev,
-+                                      "failed to unprepare transfer hardware\n");
-+                              return;
-+                      }
-+              }
-+              master->busy = false;
-+              spin_unlock_irqrestore(&master->queue_lock, flags);
-+              return;
-+      }
-+
-+      /* Make sure we are not already running a message */
-+      if (master->cur_msg) {
-+              spin_unlock_irqrestore(&master->queue_lock, flags);
-+              return;
-+      }
-+      /* Extract head of queue */
-+      master->cur_msg =
-+          list_entry(master->queue.next, struct spi_message, queue);
-+
-+      list_del_init(&master->cur_msg->queue);
-+      if (master->busy)
-+              was_busy = true;
-+      else
-+              master->busy = true;
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+
-+      if (!was_busy) {
-+              ret = master->prepare_transfer_hardware(master);
-+              if (ret) {
-+                      dev_err(&master->dev,
-+                              "failed to prepare transfer hardware\n");
-+                      return;
-+              }
-+      }
-+
-+      ret = master->transfer_one_message(master, master->cur_msg);
-+      if (ret) {
-+              dev_err(&master->dev,
-+                      "failed to transfer one message from queue\n");
-+              return;
-+      }
-+}
-+
-+static int spi_init_queue(struct spi_master *master)
-+{
-+      struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
-+
-+      INIT_LIST_HEAD(&master->queue);
-+      spin_lock_init(&master->queue_lock);
-+
-+      master->running = false;
-+      master->busy = false;
-+
-+      init_kthread_worker(&master->kworker);
-+      master->kworker_task = kthread_run(kthread_worker_fn,
-+                                         &master->kworker,
-+                                         dev_name(&master->dev));
-+      if (IS_ERR(master->kworker_task)) {
-+              dev_err(&master->dev, "failed to create message pump task\n");
-+              return -ENOMEM;
-+      }
-+      init_kthread_work(&master->pump_messages, spi_pump_messages);
-+
-+      /*
-+       * Master config will indicate if this controller should run the
-+       * message pump with high (realtime) priority to reduce the transfer
-+       * latency on the bus by minimising the delay between a transfer
-+       * request and the scheduling of the message pump thread. Without this
-+       * setting the message pump thread will remain at default priority.
-+       */
-+      if (master->rt) {
-+              dev_info(&master->dev,
-+                      "will run message pump with realtime priority\n");
-+              sched_setscheduler(master->kworker_task, SCHED_FIFO, &param);
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * spi_get_next_queued_message() - called by driver to check for queued
-+ * messages
-+ * @master: the master to check for queued messages
-+ *
-+ * If there are more messages in the queue, the next message is returned from
-+ * this call.
-+ */
-+struct spi_message *spi_get_next_queued_message(struct spi_master *master)
-+{
-+      struct spi_message *next;
-+      unsigned long flags;
-+
-+      /* get a pointer to the next message, if any */
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+      if (list_empty(&master->queue))
-+              next = NULL;
-+      else
-+              next = list_entry(master->queue.next,
-+                                struct spi_message, queue);
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+
-+      return next;
-+}
-+EXPORT_SYMBOL_GPL(spi_get_next_queued_message);
-+
-+/**
-+ * spi_finalize_current_message() - the current message is complete
-+ * @master: the master to return the message to
-+ *
-+ * Called by the driver to notify the core that the message in the front of the
-+ * queue is complete and can be removed from the queue.
-+ */
-+void spi_finalize_current_message(struct spi_master *master)
-+{
-+      struct spi_message *mesg;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+      mesg = master->cur_msg;
-+      master->cur_msg = NULL;
-+
-+      queue_kthread_work(&master->kworker, &master->pump_messages);
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+
-+      mesg->state = NULL;
-+      if (mesg->complete)
-+              mesg->complete(mesg->context);
-+}
-+EXPORT_SYMBOL_GPL(spi_finalize_current_message);
-+
-+static int spi_start_queue(struct spi_master *master)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+
-+      if (master->running || master->busy) {
-+              spin_unlock_irqrestore(&master->queue_lock, flags);
-+              return -EBUSY;
-+      }
-+
-+      master->running = true;
-+      master->cur_msg = NULL;
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+
-+      queue_kthread_work(&master->kworker, &master->pump_messages);
-+
-+      return 0;
-+}
-+
-+static int spi_stop_queue(struct spi_master *master)
-+{
-+      unsigned long flags;
-+      unsigned limit = 500;
-+      int ret = 0;
-+
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+
-+      /*
-+       * This is a bit lame, but is optimized for the common execution path.
-+       * A wait_queue on the master->busy could be used, but then the common
-+       * execution path (pump_messages) would be required to call wake_up or
-+       * friends on every SPI message. Do this instead.
-+       */
-+      while ((!list_empty(&master->queue) || master->busy) && limit--) {
-+              spin_unlock_irqrestore(&master->queue_lock, flags);
-+              msleep(10);
-+              spin_lock_irqsave(&master->queue_lock, flags);
-+      }
-+
-+      if (!list_empty(&master->queue) || master->busy)
-+              ret = -EBUSY;
-+      else
-+              master->running = false;
-+
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+
-+      if (ret) {
-+              dev_warn(&master->dev,
-+                       "could not stop message queue\n");
-+              return ret;
-+      }
-+      return ret;
-+}
-+
-+static int spi_destroy_queue(struct spi_master *master)
-+{
-+      int ret;
-+
-+      ret = spi_stop_queue(master);
-+
-+      /*
-+       * flush_kthread_worker will block until all work is done.
-+       * If the reason that stop_queue timed out is that the work will never
-+       * finish, then it does no good to call flush/stop thread, so
-+       * return anyway.
-+       */
-+      if (ret) {
-+              dev_err(&master->dev, "problem destroying queue\n");
-+              return ret;
-+      }
-+
-+      flush_kthread_worker(&master->kworker);
-+      kthread_stop(master->kworker_task);
-+
-+      return 0;
-+}
-+
-+/**
-+ * spi_queued_transfer - transfer function for queued transfers
-+ * @spi: spi device which is requesting transfer
-+ * @msg: spi message which is to handled is queued to driver queue
-+ */
-+static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
-+{
-+      struct spi_master *master = spi->master;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&master->queue_lock, flags);
-+
-+      if (!master->running) {
-+              spin_unlock_irqrestore(&master->queue_lock, flags);
-+              return -ESHUTDOWN;
-+      }
-+      msg->actual_length = 0;
-+      msg->status = -EINPROGRESS;
-+
-+      list_add_tail(&msg->queue, &master->queue);
-+      if (master->running && !master->busy)
-+              queue_kthread_work(&master->kworker, &master->pump_messages);
-+
-+      spin_unlock_irqrestore(&master->queue_lock, flags);
-+      return 0;
-+}
-+
-+static int spi_master_initialize_queue(struct spi_master *master)
-+{
-+      int ret;
-+
-+      master->queued = true;
-+      master->transfer = spi_queued_transfer;
-+
-+      /* Initialize and start queue */
-+      ret = spi_init_queue(master);
-+      if (ret) {
-+              dev_err(&master->dev, "problem initializing queue\n");
-+              goto err_init_queue;
-+      }
-+      ret = spi_start_queue(master);
-+      if (ret) {
-+              dev_err(&master->dev, "problem starting queue\n");
-+              goto err_start_queue;
-+      }
-+
-+      return 0;
-+
-+err_start_queue:
-+err_init_queue:
-+      spi_destroy_queue(master);
-+      return ret;
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
- static void spi_master_release(struct device *dev)
- {
-       struct spi_master *master;
-@@ -522,6 +812,7 @@ static struct class spi_master_class = {
- };
-+
- /**
-  * spi_alloc_master - allocate SPI master controller
-  * @dev: the controller, possibly using the platform_bus
-@@ -621,6 +912,15 @@ int spi_register_master(struct spi_maste
-       dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
-                       dynamic ? " (dynamic)" : "");
-+      /* If we're using a queued driver, start the queue */
-+      if (!master->transfer) {
-+              status = spi_master_initialize_queue(master);
-+              if (status) {
-+                      device_unregister(&master->dev);
-+                      goto done;
-+              }
-+      }
-+
-       mutex_lock(&board_lock);
-       list_add_tail(&master->list, &spi_master_list);
-       list_for_each_entry(bi, &board_list, list)
-@@ -636,7 +936,6 @@ done:
- }
- EXPORT_SYMBOL_GPL(spi_register_master);
--
- static int __unregister(struct device *dev, void *null)
- {
-       spi_unregister_device(to_spi_device(dev));
-@@ -657,6 +956,11 @@ void spi_unregister_master(struct spi_ma
- {
-       int dummy;
-+      if (master->queued) {
-+              if (spi_destroy_queue(master))
-+                      dev_err(&master->dev, "queue remove failed\n");
-+      }
-+
-       mutex_lock(&board_lock);
-       list_del(&master->list);
-       mutex_unlock(&board_lock);
-@@ -666,6 +970,37 @@ void spi_unregister_master(struct spi_ma
- }
- EXPORT_SYMBOL_GPL(spi_unregister_master);
-+int spi_master_suspend(struct spi_master *master)
-+{
-+      int ret;
-+
-+      /* Basically no-ops for non-queued masters */
-+      if (!master->queued)
-+              return 0;
-+
-+      ret = spi_stop_queue(master);
-+      if (ret)
-+              dev_err(&master->dev, "queue stop failed\n");
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(spi_master_suspend);
-+
-+int spi_master_resume(struct spi_master *master)
-+{
-+      int ret;
-+
-+      if (!master->queued)
-+              return 0;
-+
-+      ret = spi_start_queue(master);
-+      if (ret)
-+              dev_err(&master->dev, "queue restart failed\n");
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(spi_master_resume);
-+
- static int __spi_master_match(struct device *dev, void *data)
- {
-       struct spi_master *m;
---- a/include/linux/spi/spi.h
-+++ b/include/linux/spi/spi.h
-@@ -22,6 +22,7 @@
- #include <linux/device.h>
- #include <linux/mod_devicetable.h>
- #include <linux/slab.h>
-+#include <linux/kthread.h>
- /*
-  * INTERFACES between SPI master-side drivers and SPI infrastructure.
-@@ -235,6 +236,27 @@ static inline void spi_unregister_driver
-  *    the device whose settings are being modified.
-  * @transfer: adds a message to the controller's transfer queue.
-  * @cleanup: frees controller-specific state
-+ * @queued: whether this master is providing an internal message queue
-+ * @kworker: thread struct for message pump
-+ * @kworker_task: pointer to task for message pump kworker thread
-+ * @pump_messages: work struct for scheduling work to the message pump
-+ * @queue_lock: spinlock to syncronise access to message queue
-+ * @queue: message queue
-+ * @cur_msg: the currently in-flight message
-+ * @busy: message pump is busy
-+ * @running: message pump is running
-+ * @rt: whether this queue is set to run as a realtime task
-+ * @prepare_transfer_hardware: a message will soon arrive from the queue
-+ *    so the subsystem requests the driver to prepare the transfer hardware
-+ *    by issuing this call
-+ * @transfer_one_message: the subsystem calls the driver to transfer a single
-+ *    message while queuing transfers that arrive in the meantime. When the
-+ *    driver is finished with this message, it must call
-+ *    spi_finalize_current_message() so the subsystem can issue the next
-+ *    transfer
-+ * @prepare_transfer_hardware: there are currently no more messages on the
-+ *    queue so the subsystem notifies the driver that it may relax the
-+ *    hardware by issuing this call
-  *
-  * Each SPI master controller can communicate with one or more @spi_device
-  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
-@@ -318,6 +340,28 @@ struct spi_master {
-       /* called on release() to free memory provided by spi_master */
-       void                    (*cleanup)(struct spi_device *spi);
-+
-+      /*
-+       * These hooks are for drivers that want to use the generic
-+       * master transfer queueing mechanism. If these are used, the
-+       * transfer() function above must NOT be specified by the driver.
-+       * Over time we expect SPI drivers to be phased over to this API.
-+       */
-+      bool                            queued;
-+      struct kthread_worker           kworker;
-+      struct task_struct              *kworker_task;
-+      struct kthread_work             pump_messages;
-+      spinlock_t                      queue_lock;
-+      struct list_head                queue;
-+      struct spi_message              *cur_msg;
-+      bool                            busy;
-+      bool                            running;
-+      bool                            rt;
-+
-+      int (*prepare_transfer_hardware)(struct spi_master *master);
-+      int (*transfer_one_message)(struct spi_master *master,
-+                                  struct spi_message *mesg);
-+      int (*unprepare_transfer_hardware)(struct spi_master *master);
- };
- static inline void *spi_master_get_devdata(struct spi_master *master)
-@@ -343,6 +387,13 @@ static inline void spi_master_put(struct
-               put_device(&master->dev);
- }
-+/* PM calls that need to be issued by the driver */
-+extern int spi_master_suspend(struct spi_master *master);
-+extern int spi_master_resume(struct spi_master *master);
-+
-+/* Calls the driver make to interact with the message queue */
-+extern struct spi_message *spi_get_next_queued_message(struct spi_master *master);
-+extern void spi_finalize_current_message(struct spi_master *master);
- /* the spi driver core manages memory for the spi_master classdev */
- extern struct spi_master *