On Sun, 16 Oct 2022 18:05:28 +0200 Mark Kettenis <mark.kette...@xs4all.nl> wrote:
> The consensus is that calling prsignal() from interrupt context isn't > safe. See dev/fdt/dapmic.c for a way to avoid that. I put prsignal() in interrupt context after "grep -R 'prsignal.*USR2'" found other files that might do the same, arch/arm64/dev/aplsmc.c aplmbox_intr -> sc_rx_callback = rtkit_rx_callback -> rtkit_poll -> callback = aplsmc_callback -> aplsmc_handle_notification -> prsignal arch/sparc64/dev/power.c power_intr -> prsignal arch/sparc64/dev/rtc.c rtc_intr -> prsignal arch/sparc64/dev/sbus.c sbus_overtemp -> prsignal dev/pv/pvbus.c virtio_pci_config_intr -> sc_config_change = vmmci_config_change -> pvbus_shutdown -> prsignal I have edited adb.c in this diff to act like dapmic.c and use task_add(9) to call prsignal() from process context. (This diff still has the #if 0 in pm_env_intr; I will delete it.) Index: arch/macppc/dev/adb.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/dev/adb.c,v retrieving revision 1.46 diff -u -p -r1.46 adb.c --- arch/macppc/dev/adb.c 2 Jul 2022 08:50:41 -0000 1.46 +++ arch/macppc/dev/adb.c 20 Oct 2022 18:29:42 -0000 @@ -89,6 +89,7 @@ #include <sys/fcntl.h> #include <sys/proc.h> #include <sys/signalvar.h> +#include <sys/task.h> #include <sys/timeout.h> #include <sys/systm.h> @@ -242,6 +243,11 @@ int adb_intr(void *arg); void adb_cuda_autopoll(void); void adb_cuda_fileserver_mode(void); +#ifndef SMALL_KERNEL +void adb_shutdown(void *); +struct task adb_shutdown_task = TASK_INITIALIZER(adb_shutdown, NULL); +#endif + #ifdef ADB_DEBUG /* * print_single @@ -831,6 +837,49 @@ adb_soft_intr(void) } } +#ifndef SMALL_KERNEL +void +adb_shutdown(void *arg) +{ + extern int allowpowerdown; + + if (allowpowerdown == 1) { + allowpowerdown = 0; + prsignal(initprocess, SIGUSR2); + } +} +#endif /* !SMALL_KERNEL */ + +void +adb_lid_closed_intr(void) +{ +#ifndef SMALL_KERNEL + switch (lid_action) { + case 1: + /* Suspend. */ + break; + case 2: + /* Hibernate. */ + break; + } +#endif +} + +void +adb_power_button_intr(void) +{ +#ifndef SMALL_KERNEL + switch (pwr_action) { + case 1: + task_add(systq, &adb_shutdown_task); + break; + case 2: + /* Suspend. */ + break; + } +#endif +} + /* * This is my version of the ADBOp routine. It mainly just calls the @@ -1597,6 +1646,7 @@ adbattach(struct device *parent, struct adbHardware = ADB_HW_CUDA; else if (strcmp(ca->ca_name, "via-pmu") == 0) { adbHardware = ADB_HW_PMU; + pm_in_adbattach(sc->sc_dev.dv_xname); /* * Bus reset can take a long time if no adb devices are Index: arch/macppc/dev/pm_direct.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.c,v retrieving revision 1.31 diff -u -p -r1.31 pm_direct.c --- arch/macppc/dev/pm_direct.c 18 Sep 2022 21:36:41 -0000 1.31 +++ arch/macppc/dev/pm_direct.c 20 Oct 2022 18:29:42 -0000 @@ -42,6 +42,7 @@ #include <sys/param.h> #include <sys/device.h> #include <sys/systm.h> +#include <sys/sensors.h> #include <machine/cpu.h> @@ -142,6 +143,9 @@ signed char pm_receive_cmd_type[] = { -1, -1, -1, -1, -1, -1, -1, -1, }; +int pm_old_env; +struct ksensor pm_lid_sens; +struct ksensordev pm_sensdev; /* * Define the private functions @@ -161,6 +165,10 @@ int pm_send(u_char); void pm_adb_get_TALK_result(PMData *); void pm_adb_get_ADB_data(PMData *); +void pm_env_intr(PMData *); + + +extern int hw_power; /* * These variables are in adb_direct.c. @@ -413,6 +421,21 @@ pmgrop(PMData *pmdata) return rval; } +void +pm_in_adbattach(const char *devname) +{ + /* A PowerBook (including iBook) has a lid. */ + if (strncmp(hw_prod, "PowerBook", 9) == 0) { + strlcpy(pm_sensdev.xname, devname, + sizeof(pm_sensdev.xname)); + strlcpy(pm_lid_sens.desc, "lid open", + sizeof(pm_lid_sens.desc)); + pm_lid_sens.type = SENSOR_INDICATOR; + sensor_attach(&pm_sensdev, &pm_lid_sens); + sensordev_install(&pm_sensdev); + pm_lid_sens.value = 1; /* This is a guess. */ + } +} /* * My PM interrupt routine for the PB Duo series and the PB 5XX series @@ -456,9 +479,11 @@ pm_intr(void) case 0x16: /* ADB device event */ case 0x18: case 0x1e: - case PMU_INT_WAKEUP: pm_adb_get_ADB_data(&pmdata); break; + case PMU_INT_ENVIRONMENT: + pm_env_intr(&pmdata); + break; default: #ifdef ADB_DEBUG if (adb_debug) @@ -664,6 +689,41 @@ pm_adb_get_ADB_data(PMData *pmdata) } void +pm_env_intr(PMData *pmdata) +{ + int env, old; +#if 0 + int i; + + printf("pm_env_intr:"); + for (i = 3; i < pmdata->num_data; i++) + printf(" %02x", pmdata->data[i]); + printf("\n"); +#endif + + /* We might have 3 bytes data[3..5], but use only data[3]. */ + if (pmdata->num_data < 3) + return; + env = pmdata->data[3]; + old = pm_old_env; + + pm_lid_sens.value = !(env & PMU_ENV_LID_CLOSED); + if (!(old & PMU_ENV_LID_CLOSED) && (env & PMU_ENV_LID_CLOSED)) + adb_lid_closed_intr(); + + hw_power = !!(env & PMU_ENV_AC_POWER); + + /* + * Act if one presses and releases the power button on a Mac + * with no ADB keyboard. + */ + if ((old & PMU_ENV_POWER_BUTTON) && !(env & PMU_ENV_POWER_BUTTON)) + adb_power_button_intr(); + + pm_old_env = env; +} + +void pm_adb_restart(void) { PMData p; @@ -753,6 +813,7 @@ pm_battery_info(int battery, struct pmu_ pmgrop(&p); info->flags = p.data[1]; + hw_power = !!(info->flags & PMU_PWR_AC_PRESENT); switch (p.data[0]) { case 3: Index: arch/macppc/dev/pm_direct.h =================================================================== RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.h,v retrieving revision 1.14 diff -u -p -r1.14 pm_direct.h --- arch/macppc/dev/pm_direct.h 18 Sep 2022 21:36:41 -0000 1.14 +++ arch/macppc/dev/pm_direct.h 20 Oct 2022 18:29:42 -0000 @@ -49,6 +49,7 @@ typedef struct { } PMData; int pmgrop(PMData *); +void pm_in_adbattach(const char *); int pm_adb_op(u_char *, void *, void *, int); void pm_adb_restart(void); void pm_adb_poweroff(void); @@ -104,7 +105,7 @@ void pmu_fileserver_mode(int); #define PMU_INT_SNDBRT 0x08 /* sound/brightness up/down buttons */ #define PMU_INT_ADB 0x10 /* ADB autopoll or reply data */ #define PMU_INT_BATTERY 0x20 -#define PMU_INT_WAKEUP 0x40 +#define PMU_INT_ENVIRONMENT 0x40 #define PMU_INT_TICK 0x80 /* 1-second tick interrupt */ #define PMU_INT_ALL 0xff /* Mask of all interrupts */ @@ -119,6 +120,13 @@ void pmu_fileserver_mode(int); #define PMU_POW_CHARGER 0x02 /* battery charger power */ #define PMU_POW_IRLED 0x04 /* IR led power (on wallstreet) */ #define PMU_POW_MEDIABAY 0x08 /* media bay power (wallstreet/lombard ?) */ + +/* Bits from PMU_INT_ENVIRONMENT */ +#define PMU_ENV_LID_CLOSED 0x01 /* The lid is closed */ +#define PMU_ENV_AC_POWER 0x04 /* AC is plugged in */ +#define PMU_ENV_POWER_BUTTON 0x08 /* power button on ADB-less Macs */ +#define PMU_ENV_BATTERY 0x10 +#define PMU_ENV_OVER_TEMP 0x20 /* PMU PMU_POWER_EVENTS commands */ enum { Index: arch/macppc/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/macppc/include/cpu.h,v retrieving revision 1.14 diff -u -p -r1.14 cpu.h --- arch/macppc/include/cpu.h 9 Oct 2013 17:43:50 -0000 1.14 +++ arch/macppc/include/cpu.h 20 Oct 2022 18:29:42 -0000 @@ -39,12 +39,16 @@ */ #define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ #define CPU_ALTIVEC 2 /* altivec is present */ -#define CPU_MAXID 3 /* number of valid machdep ids */ +#define CPU_LIDACTION 3 /* action caused by lid close */ +#define CPU_PWRACTION 4 /* action caused by power button */ +#define CPU_MAXID 5 /* number of valid machdep ids */ #define CTL_MACHDEP_NAMES { \ { 0, 0 }, \ { "allowaperture", CTLTYPE_INT }, \ { "altivec", CTLTYPE_INT }, \ + { "lidaction", CTLTYPE_INT }, \ + { "pwraction", CTLTYPE_INT }, \ } #ifdef _KERNEL @@ -64,6 +68,9 @@ extern void (*ppc64_slew_voltage)(u_int) extern u_int32_t ticks_per_sec; extern u_int32_t ns_per_tick; + +extern int lid_action; +extern int pwr_action; #endif /* _KERNEL */ #endif /* _MACHINE_CPU_H_ */ Index: arch/macppc/macppc/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/machdep.c,v retrieving revision 1.196 diff -u -p -r1.196 machdep.c --- arch/macppc/macppc/machdep.c 19 May 2022 05:43:48 -0000 1.196 +++ arch/macppc/macppc/machdep.c 20 Oct 2022 18:29:42 -0000 @@ -117,6 +117,8 @@ void * startsym, *endsym; #ifdef APERTURE int allowaperture = 0; #endif +int lid_action = 1; +int pwr_action = 1; void dumpsys(void); int lcsplx(int ipl); /* called from LCore */ @@ -346,7 +348,7 @@ install_extint(void (*handler)(void)) extint_call = (extint_call & 0xfc000003) | offset; bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); syncicache((void *)&extint_call, sizeof extint_call); - syncicache((void *)EXC_EXI, (int)&extsize); + syncicache((void *)EXC_EXI, (size_t)&extsize); ppc_mtmsr(omsr); } @@ -533,9 +535,14 @@ sys_sigreturn(struct proc *p, void *v, r return EJUSTRETURN; } +const struct sysctl_bounded_args cpuctl_vars[] = { + { CPU_ALTIVEC, &ppc_altivec, SYSCTL_INT_READONLY }, + { CPU_LIDACTION, &lid_action, 0, 2 }, + { CPU_PWRACTION, &pwr_action, 0, 2 }, +}; + /* * Machine dependent system variables. - * None for now. */ int cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, @@ -556,10 +563,9 @@ cpu_sysctl(int *name, u_int namelen, voi #else return (sysctl_rdint(oldp, oldlenp, newp, 0)); #endif - case CPU_ALTIVEC: - return (sysctl_rdint(oldp, oldlenp, newp, ppc_altivec)); default: - return EOPNOTSUPP; + return (sysctl_bounded_arr(cpuctl_vars, nitems(cpuctl_vars), + name, namelen, oldp, oldlenp, newp, newlen)); } } Index: dev/adb/adb.h =================================================================== RCS file: /cvs/src/sys/dev/adb/adb.h,v retrieving revision 1.5 diff -u -p -r1.5 adb.h --- dev/adb/adb.h 16 Jun 2011 10:44:33 -0000 1.5 +++ dev/adb/adb.h 20 Oct 2022 18:29:42 -0000 @@ -139,6 +139,8 @@ typedef struct { } ADBDataBlock; int adbprint(void *, const char *); +void adb_lid_closed_intr(void); +void adb_power_button_intr(void); int adb_op_sync(Ptr, short); int set_adb_info(ADBSetInfoBlock *, int); Index: dev/adb/akbd.c =================================================================== RCS file: /cvs/src/sys/dev/adb/akbd.c,v retrieving revision 1.15 diff -u -p -r1.15 akbd.c --- dev/adb/akbd.c 6 Apr 2022 18:59:27 -0000 1.15 +++ dev/adb/akbd.c 20 Oct 2022 18:29:42 -0000 @@ -467,13 +467,14 @@ akbd_processevent(struct akbd_softc *sc, case 2: /* * The reset (or power) key sends 0x7f7f on press and - * 0xffff on release, and we ignore it. + * 0xffff on release. */ if (event->bytes[0] == event->bytes[1] && ADBK_KEYVAL(event->bytes[0]) == ADBK_RESET) { - if (event->bytes[0] == ADBK_KEYDOWN(ADBK_RESET)) + if (event->bytes[0] == ADBK_KEYDOWN(ADBK_RESET)) { SET(sc->sc_caps, CL_DOWN_RESET); - else { + adb_power_button_intr(); + } else { if (ISSET(sc->sc_caps, CL_DOWN_RESET)) CLR(sc->sc_caps, CL_DOWN_RESET); else if (ISSET(sc->sc_caps, CL_DOWN_ADB)) {