Merge branch 'char-misc-linus' into char-misc-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Mar 2013 23:09:30 +0000 (16:09 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Mar 2013 23:09:30 +0000 (16:09 -0700)
This picks up the MEI fixes that we need in this branch now.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
drivers/misc/mei/hw-me.c
drivers/misc/mei/init.c
drivers/misc/mei/mei_dev.h

diff --combined drivers/misc/mei/hw-me.c
@@@ -152,6 -152,20 +152,20 @@@ static void mei_me_intr_disable(struct 
  }
  
  /**
+  * mei_me_hw_reset_release - release device from the reset
+  *
+  * @dev: the device structure
+  */
+ static void mei_me_hw_reset_release(struct mei_device *dev)
+ {
+       struct mei_me_hw *hw = to_me_hw(dev);
+       u32 hcsr = mei_hcsr_read(hw);
+       hcsr |= H_IG;
+       hcsr &= ~H_RST;
+       mei_hcsr_set(hw, hcsr);
+ }
+ /**
   * mei_me_hw_reset - resets fw via mei csr register.
   *
   * @dev: the device structure
@@@ -169,18 -183,14 +183,14 @@@ static void mei_me_hw_reset(struct mei_
        if (intr_enable)
                hcsr |= H_IE;
        else
-               hcsr &= ~H_IE;
-       mei_hcsr_set(hw, hcsr);
-       hcsr = mei_hcsr_read(hw) | H_IG;
-       hcsr &= ~H_RST;
+               hcsr |= ~H_IE;
  
        mei_hcsr_set(hw, hcsr);
  
-       hcsr = mei_hcsr_read(hw);
+       if (dev->dev_state == MEI_DEV_POWER_DOWN)
+               mei_me_hw_reset_release(dev);
  
-       dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr);
+       dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw));
  }
  
  /**
@@@ -222,38 -232,6 +232,38 @@@ static bool mei_me_hw_is_ready(struct m
        return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
  }
  
 +static int mei_me_hw_ready_wait(struct mei_device *dev)
 +{
 +      int err;
 +      if (mei_me_hw_is_ready(dev))
 +              return 0;
 +
 +      mutex_unlock(&dev->device_lock);
 +      err = wait_event_interruptible_timeout(dev->wait_hw_ready,
 +                      dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT);
 +      mutex_lock(&dev->device_lock);
 +      if (!err && !dev->recvd_hw_ready) {
 +              dev_err(&dev->pdev->dev,
 +                      "wait hw ready failed. status = 0x%x\n", err);
 +              return -ETIMEDOUT;
 +      }
 +
 +      dev->recvd_hw_ready = false;
 +      return 0;
 +}
 +
 +static int mei_me_hw_start(struct mei_device *dev)
 +{
 +      int ret = mei_me_hw_ready_wait(dev);
 +      if (ret)
 +              return ret;
 +      dev_dbg(&dev->pdev->dev, "hw is ready\n");
 +
 +      mei_me_host_set_ready(dev);
 +      return ret;
 +}
 +
 +
  /**
   * mei_hbuf_filled_slots - gets number of device filled buffer slots
   *
@@@ -327,11 -305,10 +337,11 @@@ static int mei_me_write_message(struct 
                        unsigned char *buf)
  {
        struct mei_me_hw *hw = to_me_hw(dev);
 -      unsigned long rem, dw_cnt;
 +      unsigned long rem;
        unsigned long length = header->length;
        u32 *reg_buf = (u32 *)buf;
        u32 hcsr;
 +      u32 dw_cnt;
        int i;
        int empty_slots;
  
@@@ -456,6 -433,8 +466,6 @@@ irqreturn_t mei_me_irq_thread_handler(i
  {
        struct mei_device *dev = (struct mei_device *) dev_id;
        struct mei_cl_cb complete_list;
 -      struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
 -      struct mei_cl *cl;
        s32 slots;
        int rets;
        bool  bus_message_received;
                if (mei_hw_is_ready(dev)) {
                        dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
  
 -                      mei_host_set_ready(dev);
 -
 -                      dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
 -                      /* link is established * start sending messages.  */
 +                      dev->recvd_hw_ready = true;
 +                      wake_up_interruptible(&dev->wait_hw_ready);
  
 -                      dev->dev_state = MEI_DEV_INIT_CLIENTS;
 -
 -                      mei_hbm_start_req(dev);
                        mutex_unlock(&dev->device_lock);
                        return IRQ_HANDLED;
                } else {
-                       dev_dbg(&dev->pdev->dev, "FW not ready.\n");
+                       dev_dbg(&dev->pdev->dev, "Reset Completed.\n");
+                       mei_me_hw_reset_release(dev);
                        mutex_unlock(&dev->device_lock);
                        return IRQ_HANDLED;
                }
@@@ -525,19 -510,33 +536,19 @@@ end
                wake_up_interruptible(&dev->wait_recvd_msg);
                bus_message_received = false;
        }
 -      if (list_empty(&complete_list.list))
 -              return IRQ_HANDLED;
  
 +      mei_irq_compl_handler(dev, &complete_list);
  
 -      list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
 -              cl = cb_pos->cl;
 -              list_del(&cb_pos->list);
 -              if (cl) {
 -                      if (cl != &dev->iamthif_cl) {
 -                              dev_dbg(&dev->pdev->dev, "completing call back.\n");
 -                              mei_irq_complete_handler(cl, cb_pos);
 -                              cb_pos = NULL;
 -                      } else if (cl == &dev->iamthif_cl) {
 -                              mei_amthif_complete(dev, cb_pos);
 -                      }
 -              }
 -      }
        return IRQ_HANDLED;
  }
  static const struct mei_hw_ops mei_me_hw_ops = {
  
 -      .host_set_ready = mei_me_host_set_ready,
        .host_is_ready = mei_me_host_is_ready,
  
        .hw_is_ready = mei_me_hw_is_ready,
        .hw_reset = mei_me_hw_reset,
 -      .hw_config  = mei_me_hw_config,
 +      .hw_config = mei_me_hw_config,
 +      .hw_start = mei_me_hw_start,
  
        .intr_clear = mei_me_intr_clear,
        .intr_enable = mei_me_intr_enable,
diff --combined drivers/misc/mei/init.c
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/mei.h>
  
  #include "mei_dev.h"
 +#include "hbm.h"
  #include "client.h"
  
  const char *mei_dev_state_str(int state)
@@@ -48,7 -47,6 +48,7 @@@ void mei_device_init(struct mei_device 
        /* setup our list array */
        INIT_LIST_HEAD(&dev->file_list);
        mutex_init(&dev->device_lock);
 +      init_waitqueue_head(&dev->wait_hw_ready);
        init_waitqueue_head(&dev->wait_recvd_msg);
        init_waitqueue_head(&dev->wait_stop_wd);
        dev->dev_state = MEI_DEV_INITIALIZING;
@@@ -178,20 -176,6 +178,20 @@@ void mei_reset(struct mei_device *dev, 
                dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
                         mei_dev_state_str(dev->dev_state));
  
 +      if (!interrupts_enabled) {
 +              dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n");
 +              return;
 +      }
 +
 +      mei_hw_start(dev);
 +
 +      dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
 +      /* link is established * start sending messages.  */
 +
 +      dev->dev_state = MEI_DEV_INIT_CLIENTS;
 +
 +      mei_hbm_start_req(dev);
 +
        /* wake up all readings so they can be interrupted */
        mei_cl_all_read_wakeup(dev);
  
        mei_cl_all_write_clear(dev);
  }
  
+ void mei_stop(struct mei_device *dev)
+ {
+       dev_dbg(&dev->pdev->dev, "stopping the device.\n");
+       mutex_lock(&dev->device_lock);
+       cancel_delayed_work(&dev->timer_work);
+       mei_wd_stop(dev);
+       dev->dev_state = MEI_DEV_POWER_DOWN;
+       mei_reset(dev, 0);
+       mutex_unlock(&dev->device_lock);
+       flush_scheduled_work();
+ }
  
  
  
@@@ -213,11 -213,11 +213,11 @@@ struct mei_cl 
  
  /** struct mei_hw_ops
   *
 - * @host_set_ready   - notify FW that host side is ready
   * @host_is_ready    - query for host readiness
  
   * @hw_is_ready      - query if hw is ready
   * @hw_reset         - reset hw
 + * @hw_start         - start hw after reset
   * @hw_config        - configure hw
  
   * @intr_clear       - clear pending interrupts
   */
  struct mei_hw_ops {
  
 -      void (*host_set_ready) (struct mei_device *dev);
        bool (*host_is_ready) (struct mei_device *dev);
  
        bool (*hw_is_ready) (struct mei_device *dev);
        void (*hw_reset) (struct mei_device *dev, bool enable);
 +      int  (*hw_start) (struct mei_device *dev);
        void (*hw_config) (struct mei_device *dev);
  
        void (*intr_clear) (struct mei_device *dev);
@@@ -296,14 -296,11 +296,14 @@@ struct mei_device 
         */
        struct mutex device_lock; /* device lock */
        struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
 +
 +      bool recvd_hw_ready;
        bool recvd_msg;
  
        /*
         * waiting queue for receive message from FW
         */
 +      wait_queue_head_t wait_hw_ready;
        wait_queue_head_t wait_recvd_msg;
        wait_queue_head_t wait_stop_wd;
  
@@@ -377,17 -374,6 +377,17 @@@ static inline unsigned long mei_secs_to
        return msecs_to_jiffies(sec * MSEC_PER_SEC);
  }
  
 +/**
 + * mei_data2slots - get slots - number of (dwords) from a message length
 + *    + size of the mei header
 + * @length - size of the messages in bytes
 + * returns  - number of slots
 + */
 +static inline u32 mei_data2slots(size_t length)
 +{
 +      return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
 +}
 +
  
  /*
   * mei init function prototypes
  void mei_device_init(struct mei_device *dev);
  void mei_reset(struct mei_device *dev, int interrupts);
  int mei_hw_init(struct mei_device *dev);
+ void mei_stop(struct mei_device *dev);
  
  /*
   *  MEI interrupt functions prototype
@@@ -405,7 -392,8 +406,7 @@@ int mei_irq_read_handler(struct mei_dev
                struct mei_cl_cb *cmpl_list, s32 *slots);
  
  int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
 -
 -void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos);
 +void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
  
  /*
   * AMTHIF - AMT Host Interface Functions
@@@ -467,11 -455,6 +468,11 @@@ static inline void mei_hw_reset(struct 
        dev->ops->hw_reset(dev, enable);
  }
  
 +static inline void mei_hw_start(struct mei_device *dev)
 +{
 +      dev->ops->hw_start(dev);
 +}
 +
  static inline void mei_clear_interrupts(struct mei_device *dev)
  {
        dev->ops->intr_clear(dev);
@@@ -487,6 -470,10 +488,6 @@@ static inline void mei_disable_interrup
        dev->ops->intr_disable(dev);
  }
  
 -static inline void mei_host_set_ready(struct mei_device *dev)
 -{
 -      dev->ops->host_set_ready(dev);
 -}
  static inline bool mei_host_is_ready(struct mei_device *dev)
  {
        return dev->ops->host_is_ready(dev);