aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuansheng Liu <chuansheng.liu@intel.com>2012-11-08 06:14:40 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-14 18:04:23 -0500
commitce2fcbd99cef580623116bb33531dbc3e6f690b0 (patch)
treebaeea3fda4375556df4c54c1a6402f536c2a93f9
parentecdca043ebe8e3172e0400d0966831e2e60870a0 (diff)
firmware loader: Fix the race FW_STATUS_DONE is followed by class_timeout
There is a race as below when calling request_firmware(): CPU1 CPU2 write 0 > loading mutex_lock(&fw_lock) ... set_bit FW_STATUS_DONE class_timeout is coming set_bit FW_STATUS_ABORT complete_all &completion ... mutex_unlock(&fw_lock) In this time, the bit FW_STATUS_DONE and FW_STATUS_ABORT are set, and request_firmware() will return failure due to condition in _request_firmware_load(): if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) retval = -ENOENT; But from the above scenerio, it should be a successful requesting. So we need judge if the bit FW_STATUS_DONE is already set before calling fw_load_abort() in timeout function. As Ming's proposal, we need change the timer into sched_work to benefit from using &fw_lock mutex also. Signed-off-by: liu chuansheng <chuansheng.liu@intel.com> Acked-by: Ming Lei <ming.lei@canonical.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/firmware_class.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e489ed..b44ed35ac38d 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -143,7 +143,7 @@ struct fw_cache_entry {
143}; 143};
144 144
145struct firmware_priv { 145struct firmware_priv {
146 struct timer_list timeout; 146 struct delayed_work timeout_work;
147 bool nowait; 147 bool nowait;
148 struct device dev; 148 struct device dev;
149 struct firmware_buf *buf; 149 struct firmware_buf *buf;
@@ -667,11 +667,18 @@ static struct bin_attribute firmware_attr_data = {
667 .write = firmware_data_write, 667 .write = firmware_data_write,
668}; 668};
669 669
670static void firmware_class_timeout(u_long data) 670static void firmware_class_timeout_work(struct work_struct *work)
671{ 671{
672 struct firmware_priv *fw_priv = (struct firmware_priv *) data; 672 struct firmware_priv *fw_priv = container_of(work,
673 struct firmware_priv, timeout_work.work);
673 674
675 mutex_lock(&fw_lock);
676 if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
677 mutex_unlock(&fw_lock);
678 return;
679 }
674 fw_load_abort(fw_priv); 680 fw_load_abort(fw_priv);
681 mutex_unlock(&fw_lock);
675} 682}
676 683
677static struct firmware_priv * 684static struct firmware_priv *
@@ -690,8 +697,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
690 697
691 fw_priv->nowait = nowait; 698 fw_priv->nowait = nowait;
692 fw_priv->fw = firmware; 699 fw_priv->fw = firmware;
693 setup_timer(&fw_priv->timeout, 700 INIT_DELAYED_WORK(&fw_priv->timeout_work,
694 firmware_class_timeout, (u_long) fw_priv); 701 firmware_class_timeout_work);
695 702
696 f_dev = &fw_priv->dev; 703 f_dev = &fw_priv->dev;
697 704
@@ -858,7 +865,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
858 dev_dbg(f_dev->parent, "firmware: direct-loading" 865 dev_dbg(f_dev->parent, "firmware: direct-loading"
859 " firmware %s\n", buf->fw_id); 866 " firmware %s\n", buf->fw_id);
860 867
868 mutex_lock(&fw_lock);
861 set_bit(FW_STATUS_DONE, &buf->status); 869 set_bit(FW_STATUS_DONE, &buf->status);
870 mutex_unlock(&fw_lock);
862 complete_all(&buf->completion); 871 complete_all(&buf->completion);
863 direct_load = 1; 872 direct_load = 1;
864 goto handle_fw; 873 goto handle_fw;
@@ -894,15 +903,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
894 dev_set_uevent_suppress(f_dev, false); 903 dev_set_uevent_suppress(f_dev, false);
895 dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); 904 dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
896 if (timeout != MAX_SCHEDULE_TIMEOUT) 905 if (timeout != MAX_SCHEDULE_TIMEOUT)
897 mod_timer(&fw_priv->timeout, 906 schedule_delayed_work(&fw_priv->timeout_work, timeout);
898 round_jiffies_up(jiffies + timeout));
899 907
900 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); 908 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
901 } 909 }
902 910
903 wait_for_completion(&buf->completion); 911 wait_for_completion(&buf->completion);
904 912
905 del_timer_sync(&fw_priv->timeout); 913 cancel_delayed_work_sync(&fw_priv->timeout_work);
906 914
907handle_fw: 915handle_fw:
908 mutex_lock(&fw_lock); 916 mutex_lock(&fw_lock);