Commit 70b52b38 authored by Johannes Berg's avatar Johannes Berg Committed by Paul Mackerras

[POWERPC] powermac: disallow pmu sleep notifiers from aborting sleep

Tracing through the code, no current PMU sleep notifier can abort sleep.
Since no new PMU sleep notifiers should be added, this patch simplifies the
code and removes the ability to abort sleep.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 17e638bc
...@@ -90,7 +90,7 @@ static int autopoll_devs; ...@@ -90,7 +90,7 @@ static int autopoll_devs;
int __adb_probe_sync; int __adb_probe_sync;
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier adb_sleep_notifier = { static struct pmu_sleep_notifier adb_sleep_notifier = {
adb_notify_sleep, adb_notify_sleep,
SLEEP_LEVEL_ADB, SLEEP_LEVEL_ADB,
...@@ -340,11 +340,9 @@ __initcall(adb_init); ...@@ -340,11 +340,9 @@ __initcall(adb_init);
/* /*
* notify clients before sleep and reset bus afterwards * notify clients before sleep and reset bus afterwards
*/ */
int void
adb_notify_sleep(struct pmu_sleep_notifier *self, int when) adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
{ {
int ret;
switch (when) { switch (when) {
case PBOOK_SLEEP_REQUEST: case PBOOK_SLEEP_REQUEST:
adb_got_sleep = 1; adb_got_sleep = 1;
...@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) ...@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
/* Stop autopoll */ /* Stop autopoll */
if (adb_controller->autopoll) if (adb_controller->autopoll)
adb_controller->autopoll(0); adb_controller->autopoll(0);
ret = blocking_notifier_call_chain(&adb_client_list, blocking_notifier_call_chain(&adb_client_list,
ADB_MSG_POWERDOWN, NULL); ADB_MSG_POWERDOWN, NULL);
if (ret & NOTIFY_STOP_MASK) {
up(&adb_probe_mutex);
return PBOOK_SLEEP_REFUSE;
}
break;
case PBOOK_SLEEP_REJECT:
if (adb_got_sleep) {
adb_got_sleep = 0;
up(&adb_probe_mutex);
adb_reset_bus();
}
break;
case PBOOK_SLEEP_NOW:
break; break;
case PBOOK_WAKE: case PBOOK_WAKE:
adb_got_sleep = 0; adb_got_sleep = 0;
...@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) ...@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
adb_reset_bus(); adb_reset_bus();
break; break;
} }
return PBOOK_SLEEP_OK;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
static int static int
do_adb_reset_bus(void) do_adb_reset_bus(void)
{ {
int ret, nret; int ret;
if (adb_controller == NULL) if (adb_controller == NULL)
return -ENXIO; return -ENXIO;
...@@ -391,13 +374,8 @@ do_adb_reset_bus(void) ...@@ -391,13 +374,8 @@ do_adb_reset_bus(void)
if (adb_controller->autopoll) if (adb_controller->autopoll)
adb_controller->autopoll(0); adb_controller->autopoll(0);
nret = blocking_notifier_call_chain(&adb_client_list, blocking_notifier_call_chain(&adb_client_list,
ADB_MSG_PRE_RESET, NULL); ADB_MSG_PRE_RESET, NULL);
if (nret & NOTIFY_STOP_MASK) {
if (adb_controller->autopoll)
adb_controller->autopoll(autopoll_devs);
return -EBUSY;
}
if (sleepy_trackpad) { if (sleepy_trackpad) {
/* Let the trackpad settle down */ /* Let the trackpad settle down */
...@@ -427,10 +405,8 @@ do_adb_reset_bus(void) ...@@ -427,10 +405,8 @@ do_adb_reset_bus(void)
} }
up(&adb_handler_sem); up(&adb_handler_sem);
nret = blocking_notifier_call_chain(&adb_client_list, blocking_notifier_call_chain(&adb_client_list,
ADB_MSG_POST_RESET, NULL); ADB_MSG_POST_RESET, NULL);
if (nret & NOTIFY_STOP_MASK)
return -EBUSY;
return ret; return ret;
} }
......
...@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); ...@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
static struct apm_user * user_list; static struct apm_user * user_list;
static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when); static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier apm_sleep_notifier = { static struct pmu_sleep_notifier apm_sleep_notifier = {
apm_notify_sleep, apm_notify_sleep,
SLEEP_LEVEL_USERLAND, SLEEP_LEVEL_USERLAND,
...@@ -352,7 +352,7 @@ static int do_open(struct inode * inode, struct file * filp) ...@@ -352,7 +352,7 @@ static int do_open(struct inode * inode, struct file * filp)
* doesn't provide a way to NAK, but this could be added * doesn't provide a way to NAK, but this could be added
* here. * here.
*/ */
static int wait_all_suspend(void) static void wait_all_suspend(void)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -366,24 +366,19 @@ static int wait_all_suspend(void) ...@@ -366,24 +366,19 @@ static int wait_all_suspend(void)
remove_wait_queue(&apm_suspend_waitqueue, &wait); remove_wait_queue(&apm_suspend_waitqueue, &wait);
DBG("apm_emu: wait_all_suspend() - complete !\n"); DBG("apm_emu: wait_all_suspend() - complete !\n");
return 1;
} }
static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when) static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
{ {
switch(when) { switch(when) {
case PBOOK_SLEEP_REQUEST: case PBOOK_SLEEP_REQUEST:
queue_event(APM_SYS_SUSPEND, NULL); queue_event(APM_SYS_SUSPEND, NULL);
if (!wait_all_suspend()) wait_all_suspend();
return PBOOK_SLEEP_REFUSE;
break; break;
case PBOOK_SLEEP_REJECT:
case PBOOK_WAKE: case PBOOK_WAKE:
queue_event(APM_NORMAL_RESUME, NULL); queue_event(APM_NORMAL_RESUME, NULL);
break; break;
} }
return PBOOK_SLEEP_OK;
} }
#define APM_CRITICAL 10 #define APM_CRITICAL 10
......
...@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = { ...@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = {
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
{ {
unsigned long flags; unsigned long flags;
...@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) ...@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
break; break;
} }
spin_unlock_irqrestore(&pmu_blink_lock, flags); spin_unlock_irqrestore(&pmu_blink_lock, flags);
return PBOOK_SLEEP_OK;
} }
static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
......
...@@ -1769,35 +1769,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notifier); ...@@ -1769,35 +1769,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
#if defined(CONFIG_PM) && defined(CONFIG_PPC32) #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
/* Sleep is broadcast last-to-first */ /* Sleep is broadcast last-to-first */
static int static void broadcast_sleep(int when)
broadcast_sleep(int when, int fallback)
{ {
int ret = PBOOK_SLEEP_OK;
struct list_head *list; struct list_head *list;
struct pmu_sleep_notifier *notifier; struct pmu_sleep_notifier *notifier;
for (list = sleep_notifiers.prev; list != &sleep_notifiers; for (list = sleep_notifiers.prev; list != &sleep_notifiers;
list = list->prev) { list = list->prev) {
notifier = list_entry(list, struct pmu_sleep_notifier, list); notifier = list_entry(list, struct pmu_sleep_notifier, list);
ret = notifier->notifier_call(notifier, when); notifier->notifier_call(notifier, when);
if (ret != PBOOK_SLEEP_OK) {
printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
when, notifier, notifier->notifier_call);
for (; list != &sleep_notifiers; list = list->next) {
notifier = list_entry(list, struct pmu_sleep_notifier, list);
notifier->notifier_call(notifier, fallback);
}
return ret;
}
} }
return ret;
} }
/* Wake is broadcast first-to-last */ /* Wake is broadcast first-to-last */
static int static void broadcast_wake(void)
broadcast_wake(void)
{ {
int ret = PBOOK_SLEEP_OK;
struct list_head *list; struct list_head *list;
struct pmu_sleep_notifier *notifier; struct pmu_sleep_notifier *notifier;
...@@ -1806,7 +1792,6 @@ broadcast_wake(void) ...@@ -1806,7 +1792,6 @@ broadcast_wake(void)
notifier = list_entry(list, struct pmu_sleep_notifier, list); notifier = list_entry(list, struct pmu_sleep_notifier, list);
notifier->notifier_call(notifier, PBOOK_WAKE); notifier->notifier_call(notifier, PBOOK_WAKE);
} }
return ret;
} }
/* /*
...@@ -2013,12 +1998,8 @@ pmac_suspend_devices(void) ...@@ -2013,12 +1998,8 @@ pmac_suspend_devices(void)
pm_prepare_console(); pm_prepare_console();
/* Notify old-style device drivers & userland */ /* Notify old-style device drivers */
ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); broadcast_sleep(PBOOK_SLEEP_REQUEST);
if (ret != PBOOK_SLEEP_OK) {
printk(KERN_ERR "Sleep rejected by drivers\n");
return -EBUSY;
}
/* Sync the disks. */ /* Sync the disks. */
/* XXX It would be nice to have some way to ensure that /* XXX It would be nice to have some way to ensure that
...@@ -2028,12 +2009,7 @@ pmac_suspend_devices(void) ...@@ -2028,12 +2009,7 @@ pmac_suspend_devices(void)
*/ */
sys_sync(); sys_sync();
/* Sleep can fail now. May not be very robust but useful for debugging */ broadcast_sleep(PBOOK_SLEEP_NOW);
ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
if (ret != PBOOK_SLEEP_OK) {
printk(KERN_ERR "Driver sleep failed\n");
return -EBUSY;
}
/* Send suspend call to devices, hold the device core's dpm_sem */ /* Send suspend call to devices, hold the device core's dpm_sem */
ret = device_suspend(PMSG_SUSPEND); ret = device_suspend(PMSG_SUSPEND);
......
...@@ -168,24 +168,16 @@ extern int pmu_get_model(void); ...@@ -168,24 +168,16 @@ extern int pmu_get_model(void);
struct pmu_sleep_notifier struct pmu_sleep_notifier
{ {
int (*notifier_call)(struct pmu_sleep_notifier *self, int when); void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
int priority; int priority;
struct list_head list; struct list_head list;
}; };
/* Code values for calling sleep/wakeup handlers /* Code values for calling sleep/wakeup handlers
*
* Note: If a sleep request got cancelled, all drivers will get
* the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
*/ */
#define PBOOK_SLEEP_REQUEST 1 #define PBOOK_SLEEP_REQUEST 1
#define PBOOK_SLEEP_NOW 2 #define PBOOK_SLEEP_NOW 2
#define PBOOK_SLEEP_REJECT 3 #define PBOOK_WAKE 3
#define PBOOK_WAKE 4
/* Result codes returned by the notifiers */
#define PBOOK_SLEEP_OK 0
#define PBOOK_SLEEP_REFUSE -1
/* priority levels in notifiers */ /* priority levels in notifiers */
#define SLEEP_LEVEL_VIDEO 100 /* Video driver (first wake) */ #define SLEEP_LEVEL_VIDEO 100 /* Video driver (first wake) */
......
...@@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emergency_dbdma_cmd; ...@@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emergency_dbdma_cmd;
/* /*
* Stuff for restoring after a sleep. * Stuff for restoring after a sleep.
*/ */
static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
struct pmu_sleep_notifier awacs_sleep_notifier = { struct pmu_sleep_notifier awacs_sleep_notifier = {
awacs_sleep_notify, SLEEP_LEVEL_SOUND, awacs_sleep_notify, SLEEP_LEVEL_SOUND,
}; };
...@@ -1419,7 +1419,7 @@ load_awacs(void) ...@@ -1419,7 +1419,7 @@ load_awacs(void)
* Save state when going to sleep, restore it afterwards. * Save state when going to sleep, restore it afterwards.
*/ */
/* FIXME: sort out disabling/re-enabling of read stuff as well */ /* FIXME: sort out disabling/re-enabling of read stuff as well */
static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
{ {
unsigned long flags; unsigned long flags;
...@@ -1548,7 +1548,6 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) ...@@ -1548,7 +1548,6 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
spin_unlock_irqrestore(&dmasound.lock, flags); spin_unlock_irqrestore(&dmasound.lock, flags);
UNLOCK(); UNLOCK();
} }
return PBOOK_SLEEP_OK;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment