mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
greybus: svc_watchdog: Add sysfs file to change the behavior of bite
Currently, AP performs unipro_reset if SVC fails to response to its ping. While this error recovery is best suited for the end-user experience, errors in the UniPro network could potentially go unnoticed by the QA and fishfooders in the development phase of the project. This patch adds an option to trigger a kernel panic so logs can be collected for analysis. Testing Done: - Reproduce issue and observe kernel panic when watchdob_control is changed to 'panic' Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
6136cce89c
commit
7c4a0edb38
4 changed files with 66 additions and 8 deletions
|
@ -257,3 +257,19 @@ Contact: Greg Kroah-Hartman <greg@kroah.com>
|
||||||
Description:
|
Description:
|
||||||
If the SVC watchdog is enabled or not. Writing 0 to this
|
If the SVC watchdog is enabled or not. Writing 0 to this
|
||||||
file will disable the watchdog, writing 1 will enable it.
|
file will disable the watchdog, writing 1 will enable it.
|
||||||
|
|
||||||
|
What: /sys/bus/greybus/devices/N-svc/watchdog_action
|
||||||
|
Date: July 2016
|
||||||
|
KernelVersion: 4.XX
|
||||||
|
Contact: Greg Kroah-Hartman <greg@kroah.com>
|
||||||
|
Description:
|
||||||
|
This attribute indicates the action to be performed upon SVC
|
||||||
|
watchdog bite.
|
||||||
|
|
||||||
|
The action can be one of the "reset" or "panic". Writing either
|
||||||
|
one of the "reset" or "panic" will change the behavior of SVC
|
||||||
|
watchdog bite. Default value is "reset".
|
||||||
|
|
||||||
|
"reset" means the UniPro subsystem is to be reset.
|
||||||
|
|
||||||
|
"panic" means SVC watchdog bite will cause kernel to panic.
|
||||||
|
|
|
@ -100,6 +100,36 @@ static ssize_t watchdog_store(struct device *dev,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RW(watchdog);
|
static DEVICE_ATTR_RW(watchdog);
|
||||||
|
|
||||||
|
static ssize_t watchdog_action_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct gb_svc *svc = to_gb_svc(dev);
|
||||||
|
|
||||||
|
if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL)
|
||||||
|
return sprintf(buf, "panic\n");
|
||||||
|
else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO)
|
||||||
|
return sprintf(buf, "reset\n");
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t watchdog_action_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct gb_svc *svc = to_gb_svc(dev);
|
||||||
|
|
||||||
|
if (sysfs_streq(buf, "panic"))
|
||||||
|
svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL;
|
||||||
|
else if (sysfs_streq(buf, "reset"))
|
||||||
|
svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RW(watchdog_action);
|
||||||
|
|
||||||
static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value)
|
static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value)
|
||||||
{
|
{
|
||||||
struct gb_svc_pwrmon_rail_count_get_response response;
|
struct gb_svc_pwrmon_rail_count_get_response response;
|
||||||
|
@ -222,6 +252,7 @@ static struct attribute *svc_attrs[] = {
|
||||||
&dev_attr_ap_intf_id.attr,
|
&dev_attr_ap_intf_id.attr,
|
||||||
&dev_attr_intf_eject.attr,
|
&dev_attr_intf_eject.attr,
|
||||||
&dev_attr_watchdog.attr,
|
&dev_attr_watchdog.attr,
|
||||||
|
&dev_attr_watchdog_action.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
ATTRIBUTE_GROUPS(svc);
|
ATTRIBUTE_GROUPS(svc);
|
||||||
|
|
|
@ -20,6 +20,11 @@ enum gb_svc_state {
|
||||||
GB_SVC_STATE_SVC_HELLO,
|
GB_SVC_STATE_SVC_HELLO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum gb_svc_watchdog_bite {
|
||||||
|
GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0,
|
||||||
|
GB_SVC_WATCHDOG_BITE_PANIC_KERNEL,
|
||||||
|
};
|
||||||
|
|
||||||
struct gb_svc_watchdog;
|
struct gb_svc_watchdog;
|
||||||
|
|
||||||
struct svc_debugfs_pwrmon_rail {
|
struct svc_debugfs_pwrmon_rail {
|
||||||
|
@ -43,6 +48,7 @@ struct gb_svc {
|
||||||
u8 protocol_minor;
|
u8 protocol_minor;
|
||||||
|
|
||||||
struct gb_svc_watchdog *watchdog;
|
struct gb_svc_watchdog *watchdog;
|
||||||
|
enum gb_svc_watchdog_bite action;
|
||||||
|
|
||||||
struct dentry *debugfs_dentry;
|
struct dentry *debugfs_dentry;
|
||||||
struct svc_debugfs_pwrmon_rail *pwrmon_rails;
|
struct svc_debugfs_pwrmon_rail *pwrmon_rails;
|
||||||
|
|
|
@ -83,16 +83,21 @@ static void do_work(struct work_struct *work)
|
||||||
dev_err(&svc->dev,
|
dev_err(&svc->dev,
|
||||||
"SVC ping has returned %d, something is wrong!!!\n",
|
"SVC ping has returned %d, something is wrong!!!\n",
|
||||||
retval);
|
retval);
|
||||||
dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n");
|
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&reset_work, greybus_reset);
|
if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) {
|
||||||
queue_delayed_work(system_wq, &reset_work, HZ/2);
|
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);
|
||||||
* Disable ourselves, we don't want to trip again unless
|
queue_delayed_work(system_wq, &reset_work, HZ / 2);
|
||||||
* userspace wants us to.
|
|
||||||
*/
|
/*
|
||||||
watchdog->enabled = false;
|
* 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" */
|
/* resubmit our work to happen again, if we are still "alive" */
|
||||||
|
|
Loading…
Add table
Reference in a new issue