On Sun, 16 Oct 2022 18:05:28 +0200
Mark Kettenis <[email protected]> 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)) {