mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
Here is the big staging and iio driver patchsets for 4.11-rc1. We almost broke even this time around, with only a few thousand lines added overall, as we removed the old and obsolete i4l code, but added some new drivers for the RPi platform, as well as adding some new IIO drivers. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWK2j/w8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymZ1ACdFR4o6xYrWEizmao4a/u+lUZE1aIAnRmcGcIc J+leO1n9bE5iadQvKYUW =sKVA -----END PGP SIGNATURE----- Merge tag 'staging-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging/iio driver updates from Greg KH: "Here is the big staging and iio driver patchsets for 4.11-rc1. We almost broke even this time around, with only a few thousand lines added overall, as we removed the old and obsolete i4l code, but added some new drivers for the RPi platform, as well as adding some new IIO drivers. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (669 commits) Staging: vc04_services: Fix the "space prohibited" code style errors Staging: vc04_services: Fix the "wrong indent" code style errors staging: octeon: Use net_device_stats from struct net_device Staging: rtl8192u: ieee80211: ieee80211.h - style fix Staging: rtl8192u: ieee80211: ieee80211_tx.c - style fix Staging: rtl8192u: ieee80211: rtl819x_BAProc.c - style fix Staging: rtl8192u: ieee80211: ieee80211_module.c - style fix Staging: rtl8192u: ieee80211: rtl819x_TSProc.c - style fix Staging: rtl8192u: r8192U.h - style fix Staging: rtl8192u: r8192U_core.c - style fix Staging: rtl8192u: r819xU_cmdpkt.c - style fix staging: rtl8192u: blank lines aren't necessary before a close brace '}' staging: rtl8192u: Adding space after enum and struct definition staging: rtl8192u: Adding space after struct definition Staging: ks7010: Add required and preferred spaces around operators Staging: ks7010: ks*: Remove redundant blank lines Staging: ks7010: ks*: Add missing blank lines after declarations staging: visorbus, replace init_timer with setup_timer staging: vt6656: rxtx.c Removed multiple dereferencing staging: vt6656: Alignment match open parenthesis ...
198 lines
4.4 KiB
C
198 lines
4.4 KiB
C
/*
|
|
* SVC Greybus "watchdog" driver.
|
|
*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Released under the GPLv2 only.
|
|
*/
|
|
|
|
#include <linux/delay.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/workqueue.h>
|
|
#include "greybus.h"
|
|
|
|
#define SVC_WATCHDOG_PERIOD (2 * HZ)
|
|
|
|
struct gb_svc_watchdog {
|
|
struct delayed_work work;
|
|
struct gb_svc *svc;
|
|
bool enabled;
|
|
struct notifier_block pm_notifier;
|
|
};
|
|
|
|
static struct delayed_work reset_work;
|
|
|
|
static int svc_watchdog_pm_notifier(struct notifier_block *notifier,
|
|
unsigned long pm_event, void *unused)
|
|
{
|
|
struct gb_svc_watchdog *watchdog =
|
|
container_of(notifier, struct gb_svc_watchdog, pm_notifier);
|
|
|
|
switch (pm_event) {
|
|
case PM_SUSPEND_PREPARE:
|
|
gb_svc_watchdog_disable(watchdog->svc);
|
|
break;
|
|
case PM_POST_SUSPEND:
|
|
gb_svc_watchdog_enable(watchdog->svc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
static void greybus_reset(struct work_struct *work)
|
|
{
|
|
static char const start_path[] = "/system/bin/start";
|
|
static char *envp[] = {
|
|
"HOME=/",
|
|
"PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin",
|
|
NULL,
|
|
};
|
|
static char *argv[] = {
|
|
(char *)start_path,
|
|
"unipro_reset",
|
|
NULL,
|
|
};
|
|
|
|
pr_err("svc_watchdog: calling \"%s %s\" to reset greybus network!\n",
|
|
argv[0], argv[1]);
|
|
call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC);
|
|
}
|
|
|
|
static void do_work(struct work_struct *work)
|
|
{
|
|
struct gb_svc_watchdog *watchdog;
|
|
struct gb_svc *svc;
|
|
int retval;
|
|
|
|
watchdog = container_of(work, struct gb_svc_watchdog, work.work);
|
|
svc = watchdog->svc;
|
|
|
|
dev_dbg(&svc->dev, "%s: ping.\n", __func__);
|
|
retval = gb_svc_ping(svc);
|
|
if (retval) {
|
|
/*
|
|
* Something went really wrong, let's warn userspace and then
|
|
* pull the plug and reset the whole greybus network.
|
|
* We need to do this outside of this workqueue as we will be
|
|
* tearing down the svc device itself. So queue up
|
|
* yet-another-callback to do that.
|
|
*/
|
|
dev_err(&svc->dev,
|
|
"SVC ping has returned %d, something is wrong!!!\n",
|
|
retval);
|
|
|
|
if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) {
|
|
panic("SVC is not responding\n");
|
|
} else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) {
|
|
dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n");
|
|
|
|
INIT_DELAYED_WORK(&reset_work, greybus_reset);
|
|
schedule_delayed_work(&reset_work, HZ / 2);
|
|
|
|
/*
|
|
* Disable ourselves, we don't want to trip again unless
|
|
* userspace wants us to.
|
|
*/
|
|
watchdog->enabled = false;
|
|
}
|
|
}
|
|
|
|
/* resubmit our work to happen again, if we are still "alive" */
|
|
if (watchdog->enabled)
|
|
schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD);
|
|
}
|
|
|
|
int gb_svc_watchdog_create(struct gb_svc *svc)
|
|
{
|
|
struct gb_svc_watchdog *watchdog;
|
|
int retval;
|
|
|
|
if (svc->watchdog)
|
|
return 0;
|
|
|
|
watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL);
|
|
if (!watchdog)
|
|
return -ENOMEM;
|
|
|
|
watchdog->enabled = false;
|
|
watchdog->svc = svc;
|
|
INIT_DELAYED_WORK(&watchdog->work, do_work);
|
|
svc->watchdog = watchdog;
|
|
|
|
watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier;
|
|
retval = register_pm_notifier(&watchdog->pm_notifier);
|
|
if (retval) {
|
|
dev_err(&svc->dev, "error registering pm notifier(%d)\n",
|
|
retval);
|
|
goto svc_watchdog_create_err;
|
|
}
|
|
|
|
retval = gb_svc_watchdog_enable(svc);
|
|
if (retval) {
|
|
dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval);
|
|
unregister_pm_notifier(&watchdog->pm_notifier);
|
|
goto svc_watchdog_create_err;
|
|
}
|
|
return retval;
|
|
|
|
svc_watchdog_create_err:
|
|
svc->watchdog = NULL;
|
|
kfree(watchdog);
|
|
|
|
return retval;
|
|
}
|
|
|
|
void gb_svc_watchdog_destroy(struct gb_svc *svc)
|
|
{
|
|
struct gb_svc_watchdog *watchdog = svc->watchdog;
|
|
|
|
if (!watchdog)
|
|
return;
|
|
|
|
unregister_pm_notifier(&watchdog->pm_notifier);
|
|
gb_svc_watchdog_disable(svc);
|
|
svc->watchdog = NULL;
|
|
kfree(watchdog);
|
|
}
|
|
|
|
bool gb_svc_watchdog_enabled(struct gb_svc *svc)
|
|
{
|
|
if (!svc || !svc->watchdog)
|
|
return false;
|
|
return svc->watchdog->enabled;
|
|
}
|
|
|
|
int gb_svc_watchdog_enable(struct gb_svc *svc)
|
|
{
|
|
struct gb_svc_watchdog *watchdog;
|
|
|
|
if (!svc->watchdog)
|
|
return -ENODEV;
|
|
|
|
watchdog = svc->watchdog;
|
|
if (watchdog->enabled)
|
|
return 0;
|
|
|
|
watchdog->enabled = true;
|
|
schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD);
|
|
return 0;
|
|
}
|
|
|
|
int gb_svc_watchdog_disable(struct gb_svc *svc)
|
|
{
|
|
struct gb_svc_watchdog *watchdog;
|
|
|
|
if (!svc->watchdog)
|
|
return -ENODEV;
|
|
|
|
watchdog = svc->watchdog;
|
|
if (!watchdog->enabled)
|
|
return 0;
|
|
|
|
watchdog->enabled = false;
|
|
cancel_delayed_work_sync(&watchdog->work);
|
|
return 0;
|
|
}
|