| @@ -781,6 +781,8 @@ static int query_regdb(const char *alpha2) · 780 unmodified lines |
| 781 | const struct fwdb_header *hdr = regdb; | 781 | const struct fwdb_header *hdr = regdb; |
| 782 | const struct fwdb_country *country; | 782 | const struct fwdb_country *country; |
| 783 | | 783 | |
| | 784 | ASSERT_RTNL(); |
| | 785 | |
| 784 | if (IS_ERR(regdb)) | 786 | if (IS_ERR(regdb)) |
| 785 | return PTR_ERR(regdb); | 787 | return PTR_ERR(regdb); |
| 786 | | 788 | |
| @@ -796,41 +798,47 @@ static int query_regdb(const char *alpha2) · 9 unmodified lines |
| 796 | | 798 | |
| 797 | static void regdb_fw_cb(const struct firmware *fw, void *context) | 799 | static void regdb_fw_cb(const struct firmware *fw, void *context) |
| 798 | { | 800 | { |
| | 801 | int set_error = 0; |
| | 802 | bool restore = true; |
| 799 | void *db; | 803 | void *db; |
| 800 | | 804 | |
| 801 | if (!fw) { | 805 | if (!fw) { |
| 802 | pr_info("failed to load regulatory.db\n"); | 806 | pr_info("failed to load regulatory.db\n"); |
| 803 | regdb = ERR_PTR(-ENODATA); | 807 | set_error = -ENODATA; |
| 804 | goto restore; | 808 | } else if (!valid_regdb(fw->data, fw->size)) { |
| 805 | } | | |
| 806 | | | |
| 807 | if (!valid_regdb(fw->data, fw->size)) { | | |
| 808 | pr_info("loaded regulatory.db is malformed\n"); | 809 | pr_info("loaded regulatory.db is malformed\n"); |
| 809 | release_firmware(fw); | 810 | set_error = -EINVAL; |
| 810 | regdb = ERR_PTR(-EINVAL); | | |
| 811 | goto restore; | | |
| 812 | } | 811 | } |
| 813 | | 812 | |
| 814 | db = kmemdup(fw->data, fw->size, GFP_KERNEL); | 813 | rtnl_lock(); |
| 815 | release_firmware(fw); | 814 | if (WARN_ON(regdb && !IS_ERR(regdb))) { |
| | 815 | /* just restore and free new db */ |
| | 816 | } else if (set_error) { |
| | 817 | regdb = ERR_PTR(set_error); |
| | 818 | } else if (fw) { |
| | 819 | db = kmemdup(fw->data, fw->size, GFP_KERNEL); |
| | 820 | if (db) { |
| | 821 | regdb = db; |
| | 822 | restore = context && query_regdb(context); |
| | 823 | } else { |
| | 824 | restore = true; |
| | 825 | } |
| | 826 | } |
| 816 | | 827 | |
| 817 | if (!db) | 828 | if (restore) |
| 818 | goto restore; | 829 | restore_regulatory_settings(true); |
| 819 | regdb = db; | | |
| 820 | | 830 | |
| 821 | if (query_regdb(context)) | | |
| 822 | goto restore; | | |
| 823 | goto free; | | |
| 824 | restore: | | |
| 825 | rtnl_lock(); | | |
| 826 | restore_regulatory_settings(true); | | |
| 827 | rtnl_unlock(); | 831 | rtnl_unlock(); |
| 828 | free: | 832 | |
| 829 | kfree(context); | 833 | kfree(context); |
| | 834 | |
| | 835 | release_firmware(fw); |
| 830 | } | 836 | } |
| 831 | | 837 | |
| 832 | static int query_regdb_file(const char *alpha2) | 838 | static int query_regdb_file(const char *alpha2) |
| 833 | { | 839 | { |
| | 840 | ASSERT_RTNL(); |
| | 841 | |
| 834 | if (regdb) | 842 | if (regdb) |
| 835 | return query_regdb(alpha2); | 843 | return query_regdb(alpha2); |
| 836 | | 844 | |
| @@ -843,6 +851,38 @@ static int query_regdb_file(const char *alpha2) · 6 unmodified lines |
| 843 | (void *)alpha2, regdb_fw_cb); | 851 | (void *)alpha2, regdb_fw_cb); |
| 844 | } | 852 | } |
| 845 | | 853 | |
| | 854 | int reg_reload_regdb(void) |
| | 855 | { |
| | 856 | const struct firmware *fw; |
| | 857 | void *db; |
| | 858 | int err; |
| | 859 | |
| | 860 | err = request_firmware(&fw, "regulatory.db", ®_pdev->dev); |
| | 861 | if (err) |
| | 862 | return err; |
| | 863 | |
| | 864 | if (!valid_regdb(fw->data, fw->size)) { |
| | 865 | err = -ENODATA; |
| | 866 | goto out; |
| | 867 | } |
| | 868 | |
| | 869 | db = kmemdup(fw->data, fw->size, GFP_KERNEL); |
| | 870 | if (!db) { |
| | 871 | err = -ENOMEM; |
| | 872 | goto out; |
| | 873 | } |
| | 874 | |
| | 875 | rtnl_lock(); |
| | 876 | if (!IS_ERR_OR_NULL(regdb)) |
| | 877 | kfree(regdb); |
| | 878 | regdb = db; |
| | 879 | rtnl_unlock(); |
| | 880 | |
| | 881 | out: |
| | 882 | release_firmware(fw); |
| | 883 | return err; |
| | 884 | } |
| | 885 | |
| 846 | static bool reg_query_database(struct regulatory_request *request) | 886 | static bool reg_query_database(struct regulatory_request *request) |
| 847 | { | 887 | { |
| 848 | /* query internal regulatory database (if it exists) */ | 888 | /* query internal regulatory database (if it exists) */ |