Fri Oct 29 09:04:39 2010 UTC ()
Lock the _DGS values (desired output state) during the display
output switch.

ok jruoho@


(gsutre)
diff -r1.4 -r1.5 src/sys/dev/acpi/acpi_display.c

cvs diff -r1.4 -r1.5 src/sys/dev/acpi/acpi_display.c (expand / switch to unified diff)

--- src/sys/dev/acpi/acpi_display.c 2010/10/28 21:45:02 1.4
+++ src/sys/dev/acpi/acpi_display.c 2010/10/29 09:04:38 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 gsutre Exp $ */ 1/* $NetBSD: acpi_display.c,v 1.5 2010/10/29 09:04:38 gsutre Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gregoire Sutre. 8 * by Gregoire Sutre.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -56,27 +56,27 @@ @@ -56,27 +56,27 @@
56 * (sysctl). The ACPI display adapter's mutex is shared with all ACPI display 56 * (sysctl). The ACPI display adapter's mutex is shared with all ACPI display
57 * output devices attached to it. 57 * output devices attached to it.
58 * 58 *
59 * The mutex only prevents undesired interleavings of ACPI notify handlers, 59 * The mutex only prevents undesired interleavings of ACPI notify handlers,
60 * sysctl callbacks, and pmf(9) suspend/resume routines. Race conditions with 60 * sysctl callbacks, and pmf(9) suspend/resume routines. Race conditions with
61 * autoconf(9) detachment routines could, in theory, still occur. 61 * autoconf(9) detachment routines could, in theory, still occur.
62 * 62 *
63 * The array of connected output devices (sc_odinfo) is, after attachment, only 63 * The array of connected output devices (sc_odinfo) is, after attachment, only
64 * used in ACPI notify handler callbacks. Since two such callbacks cannot be 64 * used in ACPI notify handler callbacks. Since two such callbacks cannot be
65 * running simultaneously, this information does not need protection. 65 * running simultaneously, this information does not need protection.
66 */ 66 */
67 67
68#include <sys/cdefs.h> 68#include <sys/cdefs.h>
69__KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 gsutre Exp $"); 69__KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.5 2010/10/29 09:04:38 gsutre Exp $");
70 70
71#include <sys/param.h> 71#include <sys/param.h>
72#include <sys/device.h> 72#include <sys/device.h>
73#include <sys/kmem.h> 73#include <sys/kmem.h>
74#include <sys/module.h> 74#include <sys/module.h>
75#include <sys/mutex.h> 75#include <sys/mutex.h>
76#include <sys/sysctl.h> 76#include <sys/sysctl.h>
77#include <sys/systm.h> 77#include <sys/systm.h>
78 78
79#include <dev/pci/pcireg.h> 79#include <dev/pci/pcireg.h>
80#include <dev/pci/pcidevs.h> 80#include <dev/pci/pcidevs.h>
81 81
82#include <dev/acpi/acpireg.h> 82#include <dev/acpi/acpireg.h>
@@ -901,34 +901,40 @@ acpidisp_out_notify_handler(ACPI_HANDLE  @@ -901,34 +901,40 @@ acpidisp_out_notify_handler(ACPI_HANDLE
901 * (b) ACPI display notify callbacks are scheduled with AcpiOsExecute, 901 * (b) ACPI display notify callbacks are scheduled with AcpiOsExecute,
902 * (c) callbacks scheduled with AcpiOsExecute are executed sequentially. 902 * (c) callbacks scheduled with AcpiOsExecute are executed sequentially.
903 */ 903 */
904 904
905static void 905static void
906acpidisp_vga_cycle_output_device_callback(void *arg) 906acpidisp_vga_cycle_output_device_callback(void *arg)
907{ 907{
908 struct acpidisp_vga_softc *asc = arg; 908 struct acpidisp_vga_softc *asc = arg;
909 struct acpidisp_odinfo *oi = asc->sc_odinfo; 909 struct acpidisp_odinfo *oi = asc->sc_odinfo;
910 struct acpidisp_outdev *od; 910 struct acpidisp_outdev *od;
911 struct acpidisp_out_softc *osc, *last_osc; 911 struct acpidisp_out_softc *osc, *last_osc;
912 acpidisp_od_state_t state, last_state; 912 acpidisp_od_state_t state, last_state;
913 acpidisp_od_status_t status; 913 acpidisp_od_status_t status;
 914 acpidisp_bios_policy_t lock_policy;
914 uint32_t i; 915 uint32_t i;
915 916
916 if (oi == NULL) 917 if (oi == NULL)
917 return; 918 return;
918 919
919 /* Mutual exclusion with callbacks of connected output devices. */ 920 /* Mutual exclusion with callbacks of connected output devices. */
920 mutex_enter(&asc->sc_mtx); 921 mutex_enter(&asc->sc_mtx);
921 922
 923 /* Lock the _DGS values. */
 924 lock_policy = asc->sc_policy;
 925 lock_policy.fmt.output = ACPI_DISP_POLICY_OUTPUT_LOCKED;
 926 (void)acpidisp_set_policy(asc, lock_policy.raw);
 927
922 last_osc = NULL; 928 last_osc = NULL;
923 for (i = 0, od = oi->oi_dev; i < oi->oi_dev_count; i++, od++) { 929 for (i = 0, od = oi->oi_dev; i < oi->oi_dev_count; i++, od++) {
924 if (od->od_device == NULL) 930 if (od->od_device == NULL)
925 continue; 931 continue;
926 osc = device_private(od->od_device); 932 osc = device_private(od->od_device);
927 933
928 if (!(osc->sc_caps & ACPI_DISP_OUT_CAP__DSS)) 934 if (!(osc->sc_caps & ACPI_DISP_OUT_CAP__DSS))
929 continue; 935 continue;
930 if (acpidisp_get_state(osc, &state.raw)) 936 if (acpidisp_get_state(osc, &state.raw))
931 continue; 937 continue;
932 938
933 if (acpidisp_get_status(osc, &status.raw)) { 939 if (acpidisp_get_status(osc, &status.raw)) {
934 state.fmt.no_switch = 0; 940 state.fmt.no_switch = 0;
@@ -945,26 +951,29 @@ acpidisp_vga_cycle_output_device_callbac @@ -945,26 +951,29 @@ acpidisp_vga_cycle_output_device_callbac
945 951
946 if (last_osc != NULL) 952 if (last_osc != NULL)
947 (void)acpidisp_set_state(last_osc, last_state.raw); 953 (void)acpidisp_set_state(last_osc, last_state.raw);
948 954
949 last_osc = osc; 955 last_osc = osc;
950 last_state = state; 956 last_state = state;
951 } 957 }
952 958
953 if (last_osc != NULL) { 959 if (last_osc != NULL) {
954 last_state.fmt.commit = 1; 960 last_state.fmt.commit = 1;
955 (void)acpidisp_set_state(last_osc, last_state.raw); 961 (void)acpidisp_set_state(last_osc, last_state.raw);
956 } 962 }
957 963
 964 /* Restore the original BIOS policy. */
 965 (void)acpidisp_set_policy(asc, asc->sc_policy.raw);
 966
958 mutex_exit(&asc->sc_mtx); 967 mutex_exit(&asc->sc_mtx);
959} 968}
960 969
961static void 970static void
962acpidisp_vga_output_device_change_callback(void *arg) 971acpidisp_vga_output_device_change_callback(void *arg)
963{ 972{
964 struct acpidisp_vga_softc *asc = arg; 973 struct acpidisp_vga_softc *asc = arg;
965 struct acpidisp_odinfo *oi = asc->sc_odinfo; 974 struct acpidisp_odinfo *oi = asc->sc_odinfo;
966 bool switch_outputs; 975 bool switch_outputs;
967 976
968 if (oi != NULL) { 977 if (oi != NULL) {
969 kmem_free(oi->oi_dev, 978 kmem_free(oi->oi_dev,
970 oi->oi_dev_count * sizeof(*oi->oi_dev)); 979 oi->oi_dev_count * sizeof(*oi->oi_dev));