| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: subr_autoconf.c,v 1.247 2016/07/19 07:44:03 msaitoh Exp $ */ | | 1 | /* $NetBSD: subr_autoconf.c,v 1.248 2017/03/20 00:30:03 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996, 2000 Christopher G. Demetriou | | 4 | * Copyright (c) 1996, 2000 Christopher G. Demetriou |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -67,27 +67,27 @@ | | | @@ -67,27 +67,27 @@ |
67 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 67 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
68 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 68 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
69 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 69 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
70 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 70 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
71 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 71 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
72 | * SUCH DAMAGE. | | 72 | * SUCH DAMAGE. |
73 | * | | 73 | * |
74 | * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) | | 74 | * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) |
75 | * | | 75 | * |
76 | * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94 | | 76 | * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94 |
77 | */ | | 77 | */ |
78 | | | 78 | |
79 | #include <sys/cdefs.h> | | 79 | #include <sys/cdefs.h> |
80 | __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.247 2016/07/19 07:44:03 msaitoh Exp $"); | | 80 | __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.248 2017/03/20 00:30:03 riastradh Exp $"); |
81 | | | 81 | |
82 | #ifdef _KERNEL_OPT | | 82 | #ifdef _KERNEL_OPT |
83 | #include "opt_ddb.h" | | 83 | #include "opt_ddb.h" |
84 | #include "drvctl.h" | | 84 | #include "drvctl.h" |
85 | #endif | | 85 | #endif |
86 | | | 86 | |
87 | #include <sys/param.h> | | 87 | #include <sys/param.h> |
88 | #include <sys/device.h> | | 88 | #include <sys/device.h> |
89 | #include <sys/disklabel.h> | | 89 | #include <sys/disklabel.h> |
90 | #include <sys/conf.h> | | 90 | #include <sys/conf.h> |
91 | #include <sys/kauth.h> | | 91 | #include <sys/kauth.h> |
92 | #include <sys/kmem.h> | | 92 | #include <sys/kmem.h> |
93 | #include <sys/systm.h> | | 93 | #include <sys/systm.h> |
| @@ -2771,136 +2771,147 @@ deviter_visits(const deviter_t *di, devi | | | @@ -2771,136 +2771,147 @@ deviter_visits(const deviter_t *di, devi |
2771 | * Device iteration does not return device_t's in any particular | | 2771 | * Device iteration does not return device_t's in any particular |
2772 | * order. An iterator will never return the same device_t twice. | | 2772 | * order. An iterator will never return the same device_t twice. |
2773 | * Device iteration is guaranteed to complete---i.e., if deviter_next(di) | | 2773 | * Device iteration is guaranteed to complete---i.e., if deviter_next(di) |
2774 | * is called repeatedly on the same `di', it will eventually return | | 2774 | * is called repeatedly on the same `di', it will eventually return |
2775 | * NULL. It is ok to attach/detach devices during device iteration. | | 2775 | * NULL. It is ok to attach/detach devices during device iteration. |
2776 | */ | | 2776 | */ |
2777 | void | | 2777 | void |
2778 | deviter_init(deviter_t *di, deviter_flags_t flags) | | 2778 | deviter_init(deviter_t *di, deviter_flags_t flags) |
2779 | { | | 2779 | { |
2780 | device_t dv; | | 2780 | device_t dv; |
2781 | | | 2781 | |
2782 | memset(di, 0, sizeof(*di)); | | 2782 | memset(di, 0, sizeof(*di)); |
2783 | | | 2783 | |
2784 | mutex_enter(&alldevs_mtx); | | | |
2785 | if ((flags & DEVITER_F_SHUTDOWN) != 0) | | 2784 | if ((flags & DEVITER_F_SHUTDOWN) != 0) |
2786 | flags |= DEVITER_F_RW; | | 2785 | flags |= DEVITER_F_RW; |
2787 | | | 2786 | |
| | | 2787 | mutex_enter(&alldevs_mtx); |
2788 | if ((flags & DEVITER_F_RW) != 0) | | 2788 | if ((flags & DEVITER_F_RW) != 0) |
2789 | alldevs_nwrite++; | | 2789 | alldevs_nwrite++; |
2790 | else | | 2790 | else |
2791 | alldevs_nread++; | | 2791 | alldevs_nread++; |
2792 | di->di_gen = alldevs_gen++; | | 2792 | di->di_gen = alldevs_gen++; |
2793 | mutex_exit(&alldevs_mtx); | | | |
2794 | | | | |
2795 | di->di_flags = flags; | | 2793 | di->di_flags = flags; |
2796 | | | 2794 | |
2797 | switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) { | | 2795 | switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) { |
2798 | case DEVITER_F_LEAVES_FIRST: | | 2796 | case DEVITER_F_LEAVES_FIRST: |
2799 | TAILQ_FOREACH(dv, &alldevs, dv_list) { | | 2797 | TAILQ_FOREACH(dv, &alldevs, dv_list) { |
2800 | if (!deviter_visits(di, dv)) | | 2798 | if (!deviter_visits(di, dv)) |
2801 | continue; | | 2799 | continue; |
2802 | di->di_curdepth = MAX(di->di_curdepth, dv->dv_depth); | | 2800 | di->di_curdepth = MAX(di->di_curdepth, dv->dv_depth); |
2803 | } | | 2801 | } |
2804 | break; | | 2802 | break; |
2805 | case DEVITER_F_ROOT_FIRST: | | 2803 | case DEVITER_F_ROOT_FIRST: |
2806 | TAILQ_FOREACH(dv, &alldevs, dv_list) { | | 2804 | TAILQ_FOREACH(dv, &alldevs, dv_list) { |
2807 | if (!deviter_visits(di, dv)) | | 2805 | if (!deviter_visits(di, dv)) |
2808 | continue; | | 2806 | continue; |
2809 | di->di_maxdepth = MAX(di->di_maxdepth, dv->dv_depth); | | 2807 | di->di_maxdepth = MAX(di->di_maxdepth, dv->dv_depth); |
2810 | } | | 2808 | } |
2811 | break; | | 2809 | break; |
2812 | default: | | 2810 | default: |
2813 | break; | | 2811 | break; |
2814 | } | | 2812 | } |
2815 | | | 2813 | |
2816 | deviter_reinit(di); | | 2814 | deviter_reinit(di); |
| | | 2815 | mutex_exit(&alldevs_mtx); |
2817 | } | | 2816 | } |
2818 | | | 2817 | |
2819 | static void | | 2818 | static void |
2820 | deviter_reinit(deviter_t *di) | | 2819 | deviter_reinit(deviter_t *di) |
2821 | { | | 2820 | { |
| | | 2821 | |
| | | 2822 | KASSERT(mutex_owned(&alldevs_mtx)); |
2822 | if ((di->di_flags & DEVITER_F_RW) != 0) | | 2823 | if ((di->di_flags & DEVITER_F_RW) != 0) |
2823 | di->di_prev = TAILQ_LAST(&alldevs, devicelist); | | 2824 | di->di_prev = TAILQ_LAST(&alldevs, devicelist); |
2824 | else | | 2825 | else |
2825 | di->di_prev = TAILQ_FIRST(&alldevs); | | 2826 | di->di_prev = TAILQ_FIRST(&alldevs); |
2826 | } | | 2827 | } |
2827 | | | 2828 | |
2828 | device_t | | 2829 | device_t |
2829 | deviter_first(deviter_t *di, deviter_flags_t flags) | | 2830 | deviter_first(deviter_t *di, deviter_flags_t flags) |
2830 | { | | 2831 | { |
| | | 2832 | |
2831 | deviter_init(di, flags); | | 2833 | deviter_init(di, flags); |
2832 | return deviter_next(di); | | 2834 | return deviter_next(di); |
2833 | } | | 2835 | } |
2834 | | | 2836 | |
2835 | static device_t | | 2837 | static device_t |
2836 | deviter_next2(deviter_t *di) | | 2838 | deviter_next2(deviter_t *di) |
2837 | { | | 2839 | { |
2838 | device_t dv; | | 2840 | device_t dv; |
2839 | | | 2841 | |
| | | 2842 | KASSERT(mutex_owned(&alldevs_mtx)); |
| | | 2843 | |
2840 | dv = di->di_prev; | | 2844 | dv = di->di_prev; |
2841 | | | 2845 | |
2842 | if (dv == NULL) | | 2846 | if (dv == NULL) |
2843 | return NULL; | | 2847 | return NULL; |
2844 | | | 2848 | |
2845 | if ((di->di_flags & DEVITER_F_RW) != 0) | | 2849 | if ((di->di_flags & DEVITER_F_RW) != 0) |
2846 | di->di_prev = TAILQ_PREV(dv, devicelist, dv_list); | | 2850 | di->di_prev = TAILQ_PREV(dv, devicelist, dv_list); |
2847 | else | | 2851 | else |
2848 | di->di_prev = TAILQ_NEXT(dv, dv_list); | | 2852 | di->di_prev = TAILQ_NEXT(dv, dv_list); |
2849 | | | 2853 | |
2850 | return dv; | | 2854 | return dv; |
2851 | } | | 2855 | } |
2852 | | | 2856 | |
2853 | static device_t | | 2857 | static device_t |
2854 | deviter_next1(deviter_t *di) | | 2858 | deviter_next1(deviter_t *di) |
2855 | { | | 2859 | { |
2856 | device_t dv; | | 2860 | device_t dv; |
2857 | | | 2861 | |
| | | 2862 | KASSERT(mutex_owned(&alldevs_mtx)); |
| | | 2863 | |
2858 | do { | | 2864 | do { |
2859 | dv = deviter_next2(di); | | 2865 | dv = deviter_next2(di); |
2860 | } while (dv != NULL && !deviter_visits(di, dv)); | | 2866 | } while (dv != NULL && !deviter_visits(di, dv)); |
2861 | | | 2867 | |
2862 | return dv; | | 2868 | return dv; |
2863 | } | | 2869 | } |
2864 | | | 2870 | |
2865 | device_t | | 2871 | device_t |
2866 | deviter_next(deviter_t *di) | | 2872 | deviter_next(deviter_t *di) |
2867 | { | | 2873 | { |
2868 | device_t dv = NULL; | | 2874 | device_t dv = NULL; |
2869 | | | 2875 | |
| | | 2876 | mutex_enter(&alldevs_mtx); |
2870 | switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) { | | 2877 | switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) { |
2871 | case 0: | | 2878 | case 0: |
2872 | return deviter_next1(di); | | 2879 | dv = deviter_next1(di); |
| | | 2880 | break; |
2873 | case DEVITER_F_LEAVES_FIRST: | | 2881 | case DEVITER_F_LEAVES_FIRST: |
2874 | while (di->di_curdepth >= 0) { | | 2882 | while (di->di_curdepth >= 0) { |
2875 | if ((dv = deviter_next1(di)) == NULL) { | | 2883 | if ((dv = deviter_next1(di)) == NULL) { |
2876 | di->di_curdepth--; | | 2884 | di->di_curdepth--; |
2877 | deviter_reinit(di); | | 2885 | deviter_reinit(di); |
2878 | } else if (dv->dv_depth == di->di_curdepth) | | 2886 | } else if (dv->dv_depth == di->di_curdepth) |
2879 | break; | | 2887 | break; |
2880 | } | | 2888 | } |
2881 | return dv; | | 2889 | break; |
2882 | case DEVITER_F_ROOT_FIRST: | | 2890 | case DEVITER_F_ROOT_FIRST: |
2883 | while (di->di_curdepth <= di->di_maxdepth) { | | 2891 | while (di->di_curdepth <= di->di_maxdepth) { |
2884 | if ((dv = deviter_next1(di)) == NULL) { | | 2892 | if ((dv = deviter_next1(di)) == NULL) { |
2885 | di->di_curdepth++; | | 2893 | di->di_curdepth++; |
2886 | deviter_reinit(di); | | 2894 | deviter_reinit(di); |
2887 | } else if (dv->dv_depth == di->di_curdepth) | | 2895 | } else if (dv->dv_depth == di->di_curdepth) |
2888 | break; | | 2896 | break; |
2889 | } | | 2897 | } |
2890 | return dv; | | 2898 | break; |
2891 | default: | | 2899 | default: |
2892 | return NULL; | | 2900 | break; |
2893 | } | | 2901 | } |
| | | 2902 | mutex_exit(&alldevs_mtx); |
| | | 2903 | |
| | | 2904 | return dv; |
2894 | } | | 2905 | } |
2895 | | | 2906 | |
2896 | void | | 2907 | void |
2897 | deviter_release(deviter_t *di) | | 2908 | deviter_release(deviter_t *di) |
2898 | { | | 2909 | { |
2899 | bool rw = (di->di_flags & DEVITER_F_RW) != 0; | | 2910 | bool rw = (di->di_flags & DEVITER_F_RW) != 0; |
2900 | | | 2911 | |
2901 | mutex_enter(&alldevs_mtx); | | 2912 | mutex_enter(&alldevs_mtx); |
2902 | if (rw) | | 2913 | if (rw) |
2903 | --alldevs_nwrite; | | 2914 | --alldevs_nwrite; |
2904 | else | | 2915 | else |
2905 | --alldevs_nread; | | 2916 | --alldevs_nread; |
2906 | /* XXX wake a garbage-collection thread */ | | 2917 | /* XXX wake a garbage-collection thread */ |