Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Lin and committed by
Greg Kroah-Hartman
7c4a0edb 6136cce8

+66 -8
+16
drivers/staging/greybus/Documentation/sysfs-bus-greybus
··· 257 257 Description: 258 258 If the SVC watchdog is enabled or not. Writing 0 to this 259 259 file will disable the watchdog, writing 1 will enable it. 260 + 261 + What: /sys/bus/greybus/devices/N-svc/watchdog_action 262 + Date: July 2016 263 + KernelVersion: 4.XX 264 + Contact: Greg Kroah-Hartman <greg@kroah.com> 265 + Description: 266 + This attribute indicates the action to be performed upon SVC 267 + watchdog bite. 268 + 269 + The action can be one of the "reset" or "panic". Writing either 270 + one of the "reset" or "panic" will change the behavior of SVC 271 + watchdog bite. Default value is "reset". 272 + 273 + "reset" means the UniPro subsystem is to be reset. 274 + 275 + "panic" means SVC watchdog bite will cause kernel to panic.
+31
drivers/staging/greybus/svc.c
··· 100 100 } 101 101 static DEVICE_ATTR_RW(watchdog); 102 102 103 + static ssize_t watchdog_action_show(struct device *dev, 104 + struct device_attribute *attr, char *buf) 105 + { 106 + struct gb_svc *svc = to_gb_svc(dev); 107 + 108 + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) 109 + return sprintf(buf, "panic\n"); 110 + else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) 111 + return sprintf(buf, "reset\n"); 112 + 113 + return -EINVAL; 114 + } 115 + 116 + static ssize_t watchdog_action_store(struct device *dev, 117 + struct device_attribute *attr, 118 + const char *buf, size_t len) 119 + { 120 + struct gb_svc *svc = to_gb_svc(dev); 121 + 122 + if (sysfs_streq(buf, "panic")) 123 + svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL; 124 + else if (sysfs_streq(buf, "reset")) 125 + svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO; 126 + else 127 + return -EINVAL; 128 + 129 + return len; 130 + } 131 + static DEVICE_ATTR_RW(watchdog_action); 132 + 103 133 static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) 104 134 { 105 135 struct gb_svc_pwrmon_rail_count_get_response response; ··· 252 222 &dev_attr_ap_intf_id.attr, 253 223 &dev_attr_intf_eject.attr, 254 224 &dev_attr_watchdog.attr, 225 + &dev_attr_watchdog_action.attr, 255 226 NULL, 256 227 }; 257 228 ATTRIBUTE_GROUPS(svc);
+6
drivers/staging/greybus/svc.h
··· 20 20 GB_SVC_STATE_SVC_HELLO, 21 21 }; 22 22 23 + enum gb_svc_watchdog_bite { 24 + GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, 25 + GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, 26 + }; 27 + 23 28 struct gb_svc_watchdog; 24 29 25 30 struct svc_debugfs_pwrmon_rail { ··· 48 43 u8 protocol_minor; 49 44 50 45 struct gb_svc_watchdog *watchdog; 46 + enum gb_svc_watchdog_bite action; 51 47 52 48 struct dentry *debugfs_dentry; 53 49 struct svc_debugfs_pwrmon_rail *pwrmon_rails;
+13 -8
drivers/staging/greybus/svc_watchdog.c
··· 83 83 dev_err(&svc->dev, 84 84 "SVC ping has returned %d, something is wrong!!!\n", 85 85 retval); 86 - dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); 87 86 88 - INIT_DELAYED_WORK(&reset_work, greybus_reset); 89 - queue_delayed_work(system_wq, &reset_work, HZ/2); 87 + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { 88 + panic("SVC is not responding\n"); 89 + } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { 90 + dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); 90 91 91 - /* 92 - * Disable ourselves, we don't want to trip again unless 93 - * userspace wants us to. 94 - */ 95 - watchdog->enabled = false; 92 + INIT_DELAYED_WORK(&reset_work, greybus_reset); 93 + queue_delayed_work(system_wq, &reset_work, HZ / 2); 94 + 95 + /* 96 + * Disable ourselves, we don't want to trip again unless 97 + * userspace wants us to. 98 + */ 99 + watchdog->enabled = false; 100 + } 96 101 } 97 102 98 103 /* resubmit our work to happen again, if we are still "alive" */