| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: acpi_ec.c,v 1.94 2023/07/18 10:04:40 riastradh Exp $ */ | | 1 | /* $NetBSD: acpi_ec.c,v 1.95 2023/07/18 10:04:50 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. | | 4 | * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. |
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 | * | | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in | | 14 | * notice, this list of conditions and the following disclaimer in |
| @@ -47,27 +47,27 @@ | | | @@ -47,27 +47,27 @@ |
47 | * working and the handlers just busy loop. | | 47 | * working and the handlers just busy loop. |
48 | * | | 48 | * |
49 | * A callout is scheduled to compensate for missing interrupts on some | | 49 | * A callout is scheduled to compensate for missing interrupts on some |
50 | * hardware. If the EC doesn't process a request for 5s, it is most likely | | 50 | * hardware. If the EC doesn't process a request for 5s, it is most likely |
51 | * in a wedged state. No method to reset the EC is currently known. | | 51 | * in a wedged state. No method to reset the EC is currently known. |
52 | * | | 52 | * |
53 | * Special care has to be taken to not poll the EC in a busy loop without | | 53 | * Special care has to be taken to not poll the EC in a busy loop without |
54 | * delay. This can prevent processing of Power Button events. At least some | | 54 | * delay. This can prevent processing of Power Button events. At least some |
55 | * Lenovo Thinkpads seem to be implement the Power Button Override in the EC | | 55 | * Lenovo Thinkpads seem to be implement the Power Button Override in the EC |
56 | * and the only option to recover on those models is to cut off all power. | | 56 | * and the only option to recover on those models is to cut off all power. |
57 | */ | | 57 | */ |
58 | | | 58 | |
59 | #include <sys/cdefs.h> | | 59 | #include <sys/cdefs.h> |
60 | __KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.94 2023/07/18 10:04:40 riastradh Exp $"); | | 60 | __KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.95 2023/07/18 10:04:50 riastradh Exp $"); |
61 | | | 61 | |
62 | #ifdef _KERNEL_OPT | | 62 | #ifdef _KERNEL_OPT |
63 | #include "opt_acpi_ec.h" | | 63 | #include "opt_acpi_ec.h" |
64 | #endif | | 64 | #endif |
65 | | | 65 | |
66 | #include <sys/param.h> | | 66 | #include <sys/param.h> |
67 | #include <sys/callout.h> | | 67 | #include <sys/callout.h> |
68 | #include <sys/condvar.h> | | 68 | #include <sys/condvar.h> |
69 | #include <sys/device.h> | | 69 | #include <sys/device.h> |
70 | #include <sys/kernel.h> | | 70 | #include <sys/kernel.h> |
71 | #include <sys/kthread.h> | | 71 | #include <sys/kthread.h> |
72 | #include <sys/mutex.h> | | 72 | #include <sys/mutex.h> |
73 | #include <sys/systm.h> | | 73 | #include <sys/systm.h> |
| @@ -685,37 +685,41 @@ acpiec_read(device_t dv, uint8_t addr, u | | | @@ -685,37 +685,41 @@ acpiec_read(device_t dv, uint8_t addr, u |
685 | | | 685 | |
686 | if (cold || acpiec_cold) { | | 686 | if (cold || acpiec_cold) { |
687 | while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) { | | 687 | while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) { |
688 | delay(1000); | | 688 | delay(1000); |
689 | acpiec_gpe_state_machine(dv); | | 689 | acpiec_gpe_state_machine(dv); |
690 | } | | 690 | } |
691 | if (sc->sc_state != EC_STATE_FREE) { | | 691 | if (sc->sc_state != EC_STATE_FREE) { |
692 | mutex_exit(&sc->sc_mtx); | | 692 | mutex_exit(&sc->sc_mtx); |
693 | acpiec_unlock(dv); | | 693 | acpiec_unlock(dv); |
694 | aprint_error_dev(dv, "command timed out, state %d\n", | | 694 | aprint_error_dev(dv, "command timed out, state %d\n", |
695 | sc->sc_state); | | 695 | sc->sc_state); |
696 | return AE_ERROR; | | 696 | return AE_ERROR; |
697 | } | | 697 | } |
698 | } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) { | | 698 | } else { |
699 | /* | | 699 | const unsigned deadline = getticks() + EC_CMD_TIMEOUT*hz; |
700 | * XXX while (sc->sc_state != EC_STATE_FREE) | | 700 | unsigned delta; |
701 | * cv_timedwait(...), | | 701 | |
702 | * plus deadline | | 702 | while (sc->sc_state != EC_STATE_FREE && |
703 | */ | | 703 | (delta = deadline - getticks()) < INT_MAX) |
704 | mutex_exit(&sc->sc_mtx); | | 704 | (void)cv_timedwait(&sc->sc_cv, &sc->sc_mtx, delta); |
705 | acpiec_unlock(dv); | | 705 | if (sc->sc_state != EC_STATE_FREE) { |
706 | aprint_error_dev(dv, | | 706 | mutex_exit(&sc->sc_mtx); |
707 | "command takes over %d sec...\n", EC_CMD_TIMEOUT); | | 707 | acpiec_unlock(dv); |
708 | return AE_ERROR; | | 708 | aprint_error_dev(dv, |
| | | 709 | "command takes over %d sec...\n", |
| | | 710 | EC_CMD_TIMEOUT); |
| | | 711 | return AE_ERROR; |
| | | 712 | } |
709 | } | | 713 | } |
710 | | | 714 | |
711 | done: | | 715 | done: |
712 | DPRINTF(ACPIEC_DEBUG_RW, sc, | | 716 | DPRINTF(ACPIEC_DEBUG_RW, sc, |
713 | "pid %ld %s, lid %ld%s%s: read addr 0x%"PRIx8": 0x%"PRIx8"\n", | | 717 | "pid %ld %s, lid %ld%s%s: read addr 0x%"PRIx8": 0x%"PRIx8"\n", |
714 | (long)curproc->p_pid, curproc->p_comm, | | 718 | (long)curproc->p_pid, curproc->p_comm, |
715 | (long)curlwp->l_lid, curlwp->l_name ? " " : "", | | 719 | (long)curlwp->l_lid, curlwp->l_name ? " " : "", |
716 | curlwp->l_name ? curlwp->l_name : "", | | 720 | curlwp->l_name ? curlwp->l_name : "", |
717 | addr, sc->sc_cur_val); | | 721 | addr, sc->sc_cur_val); |
718 | | | 722 | |
719 | *val = sc->sc_cur_val; | | 723 | *val = sc->sc_cur_val; |
720 | | | 724 | |
721 | mutex_exit(&sc->sc_mtx); | | 725 | mutex_exit(&sc->sc_mtx); |
| @@ -754,37 +758,41 @@ acpiec_write(device_t dv, uint8_t addr, | | | @@ -754,37 +758,41 @@ acpiec_write(device_t dv, uint8_t addr, |
754 | | | 758 | |
755 | if (cold || acpiec_cold) { | | 759 | if (cold || acpiec_cold) { |
756 | while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) { | | 760 | while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) { |
757 | delay(1000); | | 761 | delay(1000); |
758 | acpiec_gpe_state_machine(dv); | | 762 | acpiec_gpe_state_machine(dv); |
759 | } | | 763 | } |
760 | if (sc->sc_state != EC_STATE_FREE) { | | 764 | if (sc->sc_state != EC_STATE_FREE) { |
761 | mutex_exit(&sc->sc_mtx); | | 765 | mutex_exit(&sc->sc_mtx); |
762 | acpiec_unlock(dv); | | 766 | acpiec_unlock(dv); |
763 | aprint_error_dev(dv, "command timed out, state %d\n", | | 767 | aprint_error_dev(dv, "command timed out, state %d\n", |
764 | sc->sc_state); | | 768 | sc->sc_state); |
765 | return AE_ERROR; | | 769 | return AE_ERROR; |
766 | } | | 770 | } |
767 | } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) { | | 771 | } else { |
768 | /* | | 772 | const unsigned deadline = getticks() + EC_CMD_TIMEOUT*hz; |
769 | * XXX while (sc->sc_state != EC_STATE_FREE) | | 773 | unsigned delta; |
770 | * cv_timedwait(...), | | 774 | |
771 | * plus deadline | | 775 | while (sc->sc_state != EC_STATE_FREE && |
772 | */ | | 776 | (delta = deadline - getticks()) < INT_MAX) |
773 | mutex_exit(&sc->sc_mtx); | | 777 | (void)cv_timedwait(&sc->sc_cv, &sc->sc_mtx, delta); |
774 | acpiec_unlock(dv); | | 778 | if (sc->sc_state != EC_STATE_FREE) { |
775 | aprint_error_dev(dv, | | 779 | mutex_exit(&sc->sc_mtx); |
776 | "command takes over %d sec...\n", EC_CMD_TIMEOUT); | | 780 | acpiec_unlock(dv); |
777 | return AE_ERROR; | | 781 | aprint_error_dev(dv, |
| | | 782 | "command takes over %d sec...\n", |
| | | 783 | EC_CMD_TIMEOUT); |
| | | 784 | return AE_ERROR; |
| | | 785 | } |
778 | } | | 786 | } |
779 | | | 787 | |
780 | done: | | 788 | done: |
781 | DPRINTF(ACPIEC_DEBUG_RW, sc, | | 789 | DPRINTF(ACPIEC_DEBUG_RW, sc, |
782 | "pid %ld %s, lid %ld%s%s: write addr 0x%"PRIx8": 0x%"PRIx8 | | 790 | "pid %ld %s, lid %ld%s%s: write addr 0x%"PRIx8": 0x%"PRIx8 |
783 | " done\n", | | 791 | " done\n", |
784 | (long)curproc->p_pid, curproc->p_comm, | | 792 | (long)curproc->p_pid, curproc->p_comm, |
785 | (long)curlwp->l_lid, curlwp->l_name ? " " : "", | | 793 | (long)curlwp->l_lid, curlwp->l_name ? " " : "", |
786 | curlwp->l_name ? curlwp->l_name : "", | | 794 | curlwp->l_name ? curlwp->l_name : "", |
787 | addr, val); | | 795 | addr, val); |
788 | | | 796 | |
789 | mutex_exit(&sc->sc_mtx); | | 797 | mutex_exit(&sc->sc_mtx); |
790 | acpiec_unlock(dv); | | 798 | acpiec_unlock(dv); |