Merge branch 'driver-core-linus' into driver-core-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jun 2013 03:26:43 +0000 (20:26 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jun 2013 03:26:43 +0000 (20:26 -0700)
This resolves the merge issues with drivers/base/firmware_class.c

Thanks to Ming Lei for the patch and hints on how to resolve it.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
drivers/base/firmware_class.c

index 6ede2292f67e551edc2fa1cef331572a7f84dfec,01e21037d8feb5c04e6aedee608e9cdedc0d87bd..7fefcb5acfbf23bc5047f4c40db6fc2e89905f76
@@@ -452,35 -446,27 +452,52 @@@ static struct firmware_priv *to_firmwar
        return container_of(dev, struct firmware_priv, dev);
  }
  
- static void fw_load_abort(struct firmware_buf *buf)
 -static void fw_load_abort(struct firmware_priv *fw_priv)
++static void __fw_load_abort(struct firmware_buf *buf)
  {
 -      struct firmware_buf *buf = fw_priv->buf;
 -
+       /*
+        * There is a small window in which user can write to 'loading'
+        * between loading done and disappearance of 'loading'
+        */
+       if (test_bit(FW_STATUS_DONE, &buf->status))
+               return;
 +      list_del_init(&buf->pending_list);
        set_bit(FW_STATUS_ABORT, &buf->status);
        complete_all(&buf->completion);
 +}
 +
++static void fw_load_abort(struct firmware_priv *fw_priv)
++{
++      struct firmware_buf *buf = fw_priv->buf;
++
++      __fw_load_abort(buf);
+       /* avoid user action after loading abort */
+       fw_priv->buf = NULL;
+ }
  #define is_fw_load_aborted(buf)       \
        test_bit(FW_STATUS_ABORT, &(buf)->status)
  
-               fw_load_abort(list_first_entry(&pending_fw_head,
 +static LIST_HEAD(pending_fw_head);
 +
 +/* reboot notifier for avoid deadlock with usermode_lock */
 +static int fw_shutdown_notify(struct notifier_block *unused1,
 +                            unsigned long unused2, void *unused3)
 +{
 +      mutex_lock(&fw_lock);
 +      while (!list_empty(&pending_fw_head))
++              __fw_load_abort(list_first_entry(&pending_fw_head,
 +                                             struct firmware_buf,
 +                                             pending_list));
 +      mutex_unlock(&fw_lock);
 +      return NOTIFY_DONE;
 +}
 +
 +static struct notifier_block fw_shutdown_nb = {
 +      .notifier_call = fw_shutdown_notify,
 +};
 +
  static ssize_t firmware_timeout_show(struct class *class,
                                     struct class_attribute *attr,
                                     char *buf)
@@@ -911,23 -895,6 +927,23 @@@ static int fw_load_from_user_helper(str
        fw_priv->buf = firmware->priv;
        return _request_firmware_load(fw_priv, uevent, timeout);
  }
-                        fw_load_abort(buf);
 +
 +#ifdef CONFIG_PM_SLEEP
 +/* kill pending requests without uevent to avoid blocking suspend */
 +static void kill_requests_without_uevent(void)
 +{
 +      struct firmware_buf *buf;
 +      struct firmware_buf *next;
 +
 +      mutex_lock(&fw_lock);
 +      list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) {
 +              if (!buf->need_uevent)
++                       __fw_load_abort(buf);
 +      }
 +      mutex_unlock(&fw_lock);
 +}
 +#endif
 +
  #else /* CONFIG_FW_LOADER_USER_HELPER */
  static inline int
  fw_load_from_user_helper(struct firmware *firmware, const char *name,