diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2008-10-17 00:48:36 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-10-22 19:42:33 -0400 |
commit | 9778c14b4ca2c81e437fc2fd2b1f3d676937db27 (patch) | |
tree | ecd32dcf1fae311e7caaa400f492051aeb2c66a1 /drivers/pci/pci-acpi.c | |
parent | 2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff) |
ACPI/PCI: Fix possible race condition on _OSC evaluation
Fix possible race condition on _OSC evaluation.
Current _OSC evaluation code has possible race condition because it
maniputes osc_data linked list or its contents without any lock
mechanism.
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 89a2f0fa10f9..14848bf95e82 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -35,6 +35,8 @@ struct acpi_osc_args { | |||
35 | u32 query_result; | 35 | u32 query_result; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static DEFINE_MUTEX(pci_acpi_lock); | ||
39 | |||
38 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | 40 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) |
39 | { | 41 | { |
40 | struct acpi_osc_data *data; | 42 | struct acpi_osc_data *data; |
@@ -131,10 +133,12 @@ static acpi_status acpi_query_osc(acpi_handle handle, | |||
131 | if (ACPI_FAILURE(status)) | 133 | if (ACPI_FAILURE(status)) |
132 | return status; | 134 | return status; |
133 | 135 | ||
136 | mutex_lock(&pci_acpi_lock); | ||
134 | osc_data = acpi_get_osc_data(handle); | 137 | osc_data = acpi_get_osc_data(handle); |
135 | if (!osc_data) { | 138 | if (!osc_data) { |
136 | printk(KERN_ERR "acpi osc data array is full\n"); | 139 | printk(KERN_ERR "acpi osc data array is full\n"); |
137 | return AE_ERROR; | 140 | status = AE_ERROR; |
141 | goto out; | ||
138 | } | 142 | } |
139 | 143 | ||
140 | /* do _OSC query for all possible controls */ | 144 | /* do _OSC query for all possible controls */ |
@@ -149,7 +153,8 @@ static acpi_status acpi_query_osc(acpi_handle handle, | |||
149 | osc_data->query_result = osc_args.query_result; | 153 | osc_data->query_result = osc_args.query_result; |
150 | osc_data->is_queried = 1; | 154 | osc_data->is_queried = 1; |
151 | } | 155 | } |
152 | 156 | out: | |
157 | mutex_unlock(&pci_acpi_lock); | ||
153 | return status; | 158 | return status; |
154 | } | 159 | } |
155 | 160 | ||
@@ -190,19 +195,25 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | |||
190 | if (ACPI_FAILURE(status)) | 195 | if (ACPI_FAILURE(status)) |
191 | return status; | 196 | return status; |
192 | 197 | ||
198 | mutex_lock(&pci_acpi_lock); | ||
193 | osc_data = acpi_get_osc_data(handle); | 199 | osc_data = acpi_get_osc_data(handle); |
194 | if (!osc_data) { | 200 | if (!osc_data) { |
195 | printk(KERN_ERR "acpi osc data array is full\n"); | 201 | printk(KERN_ERR "acpi osc data array is full\n"); |
196 | return AE_ERROR; | 202 | status = AE_ERROR; |
203 | goto out; | ||
197 | } | 204 | } |
198 | 205 | ||
199 | ctrlset = (flags & OSC_CONTROL_MASKS); | 206 | ctrlset = (flags & OSC_CONTROL_MASKS); |
200 | if (!ctrlset) | 207 | if (!ctrlset) { |
201 | return AE_TYPE; | 208 | status = AE_TYPE; |
209 | goto out; | ||
210 | } | ||
202 | 211 | ||
203 | if (osc_data->is_queried && | 212 | if (osc_data->is_queried && |
204 | ((osc_data->query_result & ctrlset) != ctrlset)) | 213 | ((osc_data->query_result & ctrlset) != ctrlset)) { |
205 | return AE_SUPPORT; | 214 | status = AE_SUPPORT; |
215 | goto out; | ||
216 | } | ||
206 | 217 | ||
207 | control_set = osc_data->control_set | ctrlset; | 218 | control_set = osc_data->control_set | ctrlset; |
208 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; | 219 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; |
@@ -211,7 +222,8 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | |||
211 | status = acpi_run_osc(handle, &osc_args); | 222 | status = acpi_run_osc(handle, &osc_args); |
212 | if (ACPI_SUCCESS(status)) | 223 | if (ACPI_SUCCESS(status)) |
213 | osc_data->control_set = control_set; | 224 | osc_data->control_set = control_set; |
214 | 225 | out: | |
226 | mutex_unlock(&pci_acpi_lock); | ||
215 | return status; | 227 | return status; |
216 | } | 228 | } |
217 | EXPORT_SYMBOL(pci_osc_control_set); | 229 | EXPORT_SYMBOL(pci_osc_control_set); |