diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-19 23:26:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-19 23:26:43 -0400 |
commit | 7068cb07563d8f001e83a2836ccf1cef6518aea4 (patch) | |
tree | 1b708c157ec11f8be7f72b1db3ae3b2f903a760d /drivers/base | |
parent | bb07b00be77fb33274cb44a03bdbf2471e556189 (diff) | |
parent | 875979368eb4cfecff9f0e97625b90cc6009269d (diff) |
Merge branch 'driver-core-linus' into driver-core-next
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>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/firmware_class.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 6ede2292f67e..7fefcb5acfbf 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -452,13 +452,30 @@ static struct firmware_priv *to_firmware_priv(struct device *dev) | |||
452 | return container_of(dev, struct firmware_priv, dev); | 452 | return container_of(dev, struct firmware_priv, dev); |
453 | } | 453 | } |
454 | 454 | ||
455 | static void fw_load_abort(struct firmware_buf *buf) | 455 | static void __fw_load_abort(struct firmware_buf *buf) |
456 | { | 456 | { |
457 | /* | ||
458 | * There is a small window in which user can write to 'loading' | ||
459 | * between loading done and disappearance of 'loading' | ||
460 | */ | ||
461 | if (test_bit(FW_STATUS_DONE, &buf->status)) | ||
462 | return; | ||
463 | |||
457 | list_del_init(&buf->pending_list); | 464 | list_del_init(&buf->pending_list); |
458 | set_bit(FW_STATUS_ABORT, &buf->status); | 465 | set_bit(FW_STATUS_ABORT, &buf->status); |
459 | complete_all(&buf->completion); | 466 | complete_all(&buf->completion); |
460 | } | 467 | } |
461 | 468 | ||
469 | static void fw_load_abort(struct firmware_priv *fw_priv) | ||
470 | { | ||
471 | struct firmware_buf *buf = fw_priv->buf; | ||
472 | |||
473 | __fw_load_abort(buf); | ||
474 | |||
475 | /* avoid user action after loading abort */ | ||
476 | fw_priv->buf = NULL; | ||
477 | } | ||
478 | |||
462 | #define is_fw_load_aborted(buf) \ | 479 | #define is_fw_load_aborted(buf) \ |
463 | test_bit(FW_STATUS_ABORT, &(buf)->status) | 480 | test_bit(FW_STATUS_ABORT, &(buf)->status) |
464 | 481 | ||
@@ -470,7 +487,7 @@ static int fw_shutdown_notify(struct notifier_block *unused1, | |||
470 | { | 487 | { |
471 | mutex_lock(&fw_lock); | 488 | mutex_lock(&fw_lock); |
472 | while (!list_empty(&pending_fw_head)) | 489 | while (!list_empty(&pending_fw_head)) |
473 | fw_load_abort(list_first_entry(&pending_fw_head, | 490 | __fw_load_abort(list_first_entry(&pending_fw_head, |
474 | struct firmware_buf, | 491 | struct firmware_buf, |
475 | pending_list)); | 492 | pending_list)); |
476 | mutex_unlock(&fw_lock); | 493 | mutex_unlock(&fw_lock); |
@@ -550,7 +567,12 @@ static ssize_t firmware_loading_show(struct device *dev, | |||
550 | struct device_attribute *attr, char *buf) | 567 | struct device_attribute *attr, char *buf) |
551 | { | 568 | { |
552 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 569 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
553 | int loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status); | 570 | int loading = 0; |
571 | |||
572 | mutex_lock(&fw_lock); | ||
573 | if (fw_priv->buf) | ||
574 | loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status); | ||
575 | mutex_unlock(&fw_lock); | ||
554 | 576 | ||
555 | return sprintf(buf, "%d\n", loading); | 577 | return sprintf(buf, "%d\n", loading); |
556 | } | 578 | } |
@@ -592,12 +614,12 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
592 | const char *buf, size_t count) | 614 | const char *buf, size_t count) |
593 | { | 615 | { |
594 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 616 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
595 | struct firmware_buf *fw_buf = fw_priv->buf; | 617 | struct firmware_buf *fw_buf; |
596 | int loading = simple_strtol(buf, NULL, 10); | 618 | int loading = simple_strtol(buf, NULL, 10); |
597 | int i; | 619 | int i; |
598 | 620 | ||
599 | mutex_lock(&fw_lock); | 621 | mutex_lock(&fw_lock); |
600 | 622 | fw_buf = fw_priv->buf; | |
601 | if (!fw_buf) | 623 | if (!fw_buf) |
602 | goto out; | 624 | goto out; |
603 | 625 | ||
@@ -635,7 +657,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
635 | dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); | 657 | dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); |
636 | /* fallthrough */ | 658 | /* fallthrough */ |
637 | case -1: | 659 | case -1: |
638 | fw_load_abort(fw_buf); | 660 | fw_load_abort(fw_priv); |
639 | break; | 661 | break; |
640 | } | 662 | } |
641 | out: | 663 | out: |
@@ -703,7 +725,7 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | |||
703 | new_pages = kmalloc(new_array_size * sizeof(void *), | 725 | new_pages = kmalloc(new_array_size * sizeof(void *), |
704 | GFP_KERNEL); | 726 | GFP_KERNEL); |
705 | if (!new_pages) { | 727 | if (!new_pages) { |
706 | fw_load_abort(buf); | 728 | fw_load_abort(fw_priv); |
707 | return -ENOMEM; | 729 | return -ENOMEM; |
708 | } | 730 | } |
709 | memcpy(new_pages, buf->pages, | 731 | memcpy(new_pages, buf->pages, |
@@ -720,7 +742,7 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | |||
720 | alloc_page(GFP_KERNEL | __GFP_HIGHMEM); | 742 | alloc_page(GFP_KERNEL | __GFP_HIGHMEM); |
721 | 743 | ||
722 | if (!buf->pages[buf->nr_pages]) { | 744 | if (!buf->pages[buf->nr_pages]) { |
723 | fw_load_abort(buf); | 745 | fw_load_abort(fw_priv); |
724 | return -ENOMEM; | 746 | return -ENOMEM; |
725 | } | 747 | } |
726 | buf->nr_pages++; | 748 | buf->nr_pages++; |
@@ -800,11 +822,7 @@ static void firmware_class_timeout_work(struct work_struct *work) | |||
800 | struct firmware_priv, timeout_work.work); | 822 | struct firmware_priv, timeout_work.work); |
801 | 823 | ||
802 | mutex_lock(&fw_lock); | 824 | mutex_lock(&fw_lock); |
803 | if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) { | 825 | fw_load_abort(fw_priv); |
804 | mutex_unlock(&fw_lock); | ||
805 | return; | ||
806 | } | ||
807 | fw_load_abort(fw_priv->buf); | ||
808 | mutex_unlock(&fw_lock); | 826 | mutex_unlock(&fw_lock); |
809 | } | 827 | } |
810 | 828 | ||
@@ -886,8 +904,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
886 | 904 | ||
887 | cancel_delayed_work_sync(&fw_priv->timeout_work); | 905 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
888 | 906 | ||
889 | fw_priv->buf = NULL; | ||
890 | |||
891 | device_remove_file(f_dev, &dev_attr_loading); | 907 | device_remove_file(f_dev, &dev_attr_loading); |
892 | err_del_bin_attr: | 908 | err_del_bin_attr: |
893 | device_remove_bin_file(f_dev, &firmware_attr_data); | 909 | device_remove_bin_file(f_dev, &firmware_attr_data); |
@@ -922,7 +938,7 @@ static void kill_requests_without_uevent(void) | |||
922 | mutex_lock(&fw_lock); | 938 | mutex_lock(&fw_lock); |
923 | list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) { | 939 | list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) { |
924 | if (!buf->need_uevent) | 940 | if (!buf->need_uevent) |
925 | fw_load_abort(buf); | 941 | __fw_load_abort(buf); |
926 | } | 942 | } |
927 | mutex_unlock(&fw_lock); | 943 | mutex_unlock(&fw_lock); |
928 | } | 944 | } |