1 /* 2 * Error log support on PowerNV. 3 * 4 * Copyright 2013,2014 IBM Corp. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/of.h> 14 #include <linux/slab.h> 15 #include <linux/sysfs.h> 16 #include <linux/fs.h> 17 #include <linux/vmalloc.h> 18 #include <linux/fcntl.h> 19 #include <linux/kobject.h> 20 #include <asm/uaccess.h> 21 #include <asm/opal.h> 22 23 struct elog_obj { 24 struct kobject kobj; 25 struct bin_attribute raw_attr; 26 uint64_t id; 27 uint64_t type; 28 size_t size; 29 char *buffer; 30 }; 31 #define to_elog_obj(x) container_of(x, struct elog_obj, kobj) 32 33 struct elog_attribute { 34 struct attribute attr; 35 ssize_t (*show)(struct elog_obj *elog, struct elog_attribute *attr, 36 char *buf); 37 ssize_t (*store)(struct elog_obj *elog, struct elog_attribute *attr, 38 const char *buf, size_t count); 39 }; 40 #define to_elog_attr(x) container_of(x, struct elog_attribute, attr) 41 42 static ssize_t elog_id_show(struct elog_obj *elog_obj, 43 struct elog_attribute *attr, 44 char *buf) 45 { 46 return sprintf(buf, "0x%llx\n", elog_obj->id); 47 } 48 49 static const char *elog_type_to_string(uint64_t type) 50 { 51 switch (type) { 52 case 0: return "PEL"; 53 default: return "unknown"; 54 } 55 } 56 57 static ssize_t elog_type_show(struct elog_obj *elog_obj, 58 struct elog_attribute *attr, 59 char *buf) 60 { 61 return sprintf(buf, "0x%llx %s\n", 62 elog_obj->type, 63 elog_type_to_string(elog_obj->type)); 64 } 65 66 static ssize_t elog_ack_show(struct elog_obj *elog_obj, 67 struct elog_attribute *attr, 68 char *buf) 69 { 70 return sprintf(buf, "ack - acknowledge log message\n"); 71 } 72 73 static void delay_release_kobj(void *kobj) 74 { 75 kobject_put((struct kobject *)kobj); 76 } 77 78 static ssize_t elog_ack_store(struct elog_obj *elog_obj, 79 struct elog_attribute *attr, 80 const char *buf, 81 size_t count) 82 { 83 opal_send_ack_elog(elog_obj->id); 84 sysfs_schedule_callback(&elog_obj->kobj, delay_release_kobj, 85 &elog_obj->kobj, THIS_MODULE); 86 return count; 87 } 88 89 static struct elog_attribute id_attribute = 90 __ATTR(id, 0666, elog_id_show, NULL); 91 static struct elog_attribute type_attribute = 92 __ATTR(type, 0666, elog_type_show, NULL); 93 static struct elog_attribute ack_attribute = 94 __ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store); 95 96 static struct kset *elog_kset; 97 98 static ssize_t elog_attr_show(struct kobject *kobj, 99 struct attribute *attr, 100 char *buf) 101 { 102 struct elog_attribute *attribute; 103 struct elog_obj *elog; 104 105 attribute = to_elog_attr(attr); 106 elog = to_elog_obj(kobj); 107 108 if (!attribute->show) 109 return -EIO; 110 111 return attribute->show(elog, attribute, buf); 112 } 113 114 static ssize_t elog_attr_store(struct kobject *kobj, 115 struct attribute *attr, 116 const char *buf, size_t len) 117 { 118 struct elog_attribute *attribute; 119 struct elog_obj *elog; 120 121 attribute = to_elog_attr(attr); 122 elog = to_elog_obj(kobj); 123 124 if (!attribute->store) 125 return -EIO; 126 127 return attribute->store(elog, attribute, buf, len); 128 } 129 130 static const struct sysfs_ops elog_sysfs_ops = { 131 .show = elog_attr_show, 132 .store = elog_attr_store, 133 }; 134 135 static void elog_release(struct kobject *kobj) 136 { 137 struct elog_obj *elog; 138 139 elog = to_elog_obj(kobj); 140 kfree(elog->buffer); 141 kfree(elog); 142 } 143 144 static struct attribute *elog_default_attrs[] = { 145 &id_attribute.attr, 146 &type_attribute.attr, 147 &ack_attribute.attr, 148 NULL, 149 }; 150 151 static struct kobj_type elog_ktype = { 152 .sysfs_ops = &elog_sysfs_ops, 153 .release = &elog_release, 154 .default_attrs = elog_default_attrs, 155 }; 156 157 /* Maximum size of a single log on FSP is 16KB */ 158 #define OPAL_MAX_ERRLOG_SIZE 16384 159 160 static ssize_t raw_attr_read(struct file *filep, struct kobject *kobj, 161 struct bin_attribute *bin_attr, 162 char *buffer, loff_t pos, size_t count) 163 { 164 int opal_rc; 165 166 struct elog_obj *elog = to_elog_obj(kobj); 167 168 /* We may have had an error reading before, so let's retry */ 169 if (!elog->buffer) { 170 elog->buffer = kzalloc(elog->size, GFP_KERNEL); 171 if (!elog->buffer) 172 return -EIO; 173 174 opal_rc = opal_read_elog(__pa(elog->buffer), 175 elog->size, elog->id); 176 if (opal_rc != OPAL_SUCCESS) { 177 pr_err("ELOG: log read failed for log-id=%llx\n", 178 elog->id); 179 kfree(elog->buffer); 180 elog->buffer = NULL; 181 return -EIO; 182 } 183 } 184 185 memcpy(buffer, elog->buffer + pos, count); 186 187 return count; 188 } 189 190 static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) 191 { 192 struct elog_obj *elog; 193 int rc; 194 195 elog = kzalloc(sizeof(*elog), GFP_KERNEL); 196 if (!elog) 197 return NULL; 198 199 elog->kobj.kset = elog_kset; 200 201 kobject_init(&elog->kobj, &elog_ktype); 202 203 sysfs_bin_attr_init(&elog->raw_attr); 204 205 elog->raw_attr.attr.name = "raw"; 206 elog->raw_attr.attr.mode = 0400; 207 elog->raw_attr.size = size; 208 elog->raw_attr.read = raw_attr_read; 209 210 elog->id = id; 211 elog->size = size; 212 elog->type = type; 213 214 elog->buffer = kzalloc(elog->size, GFP_KERNEL); 215 216 if (elog->buffer) { 217 rc = opal_read_elog(__pa(elog->buffer), 218 elog->size, elog->id); 219 if (rc != OPAL_SUCCESS) { 220 pr_err("ELOG: log read failed for log-id=%llx\n", 221 elog->id); 222 kfree(elog->buffer); 223 elog->buffer = NULL; 224 } 225 } 226 227 rc = kobject_add(&elog->kobj, NULL, "0x%llx", id); 228 if (rc) { 229 kobject_put(&elog->kobj); 230 return NULL; 231 } 232 233 rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr); 234 if (rc) { 235 kobject_put(&elog->kobj); 236 return NULL; 237 } 238 239 kobject_uevent(&elog->kobj, KOBJ_ADD); 240 241 return elog; 242 } 243 244 static void elog_work_fn(struct work_struct *work) 245 { 246 size_t elog_size; 247 uint64_t log_id; 248 uint64_t elog_type; 249 int rc; 250 char name[2+16+1]; 251 252 rc = opal_get_elog_size(&log_id, &elog_size, &elog_type); 253 if (rc != OPAL_SUCCESS) { 254 pr_err("ELOG: Opal log read failed\n"); 255 return; 256 } 257 258 BUG_ON(elog_size > OPAL_MAX_ERRLOG_SIZE); 259 260 if (elog_size >= OPAL_MAX_ERRLOG_SIZE) 261 elog_size = OPAL_MAX_ERRLOG_SIZE; 262 263 sprintf(name, "0x%llx", log_id); 264 265 /* we may get notified twice, let's handle 266 * that gracefully and not create two conflicting 267 * entries. 268 */ 269 if (kset_find_obj(elog_kset, name)) 270 return; 271 272 create_elog_obj(log_id, elog_size, elog_type); 273 } 274 275 static DECLARE_WORK(elog_work, elog_work_fn); 276 277 static int elog_event(struct notifier_block *nb, 278 unsigned long events, void *change) 279 { 280 /* check for error log event */ 281 if (events & OPAL_EVENT_ERROR_LOG_AVAIL) 282 schedule_work(&elog_work); 283 return 0; 284 } 285 286 static struct notifier_block elog_nb = { 287 .notifier_call = elog_event, 288 .next = NULL, 289 .priority = 0 290 }; 291 292 int __init opal_elog_init(void) 293 { 294 int rc = 0; 295 296 elog_kset = kset_create_and_add("elog", NULL, opal_kobj); 297 if (!elog_kset) { 298 pr_warn("%s: failed to create elog kset\n", __func__); 299 return -1; 300 } 301 302 rc = opal_notifier_register(&elog_nb); 303 if (rc) { 304 pr_err("%s: Can't register OPAL event notifier (%d)\n", 305 __func__, rc); 306 return rc; 307 } 308 309 /* We are now ready to pull error logs from opal. */ 310 opal_resend_pending_logs(); 311 312 return 0; 313 } 314