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 ssize_t elog_ack_store(struct elog_obj *elog_obj, 74 struct elog_attribute *attr, 75 const char *buf, 76 size_t count) 77 { 78 opal_send_ack_elog(elog_obj->id); 79 sysfs_remove_file_self(&elog_obj->kobj, &attr->attr); 80 kobject_put(&elog_obj->kobj); 81 return count; 82 } 83 84 static struct elog_attribute id_attribute = 85 __ATTR(id, 0666, elog_id_show, NULL); 86 static struct elog_attribute type_attribute = 87 __ATTR(type, 0666, elog_type_show, NULL); 88 static struct elog_attribute ack_attribute = 89 __ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store); 90 91 static struct kset *elog_kset; 92 93 static ssize_t elog_attr_show(struct kobject *kobj, 94 struct attribute *attr, 95 char *buf) 96 { 97 struct elog_attribute *attribute; 98 struct elog_obj *elog; 99 100 attribute = to_elog_attr(attr); 101 elog = to_elog_obj(kobj); 102 103 if (!attribute->show) 104 return -EIO; 105 106 return attribute->show(elog, attribute, buf); 107 } 108 109 static ssize_t elog_attr_store(struct kobject *kobj, 110 struct attribute *attr, 111 const char *buf, size_t len) 112 { 113 struct elog_attribute *attribute; 114 struct elog_obj *elog; 115 116 attribute = to_elog_attr(attr); 117 elog = to_elog_obj(kobj); 118 119 if (!attribute->store) 120 return -EIO; 121 122 return attribute->store(elog, attribute, buf, len); 123 } 124 125 static const struct sysfs_ops elog_sysfs_ops = { 126 .show = elog_attr_show, 127 .store = elog_attr_store, 128 }; 129 130 static void elog_release(struct kobject *kobj) 131 { 132 struct elog_obj *elog; 133 134 elog = to_elog_obj(kobj); 135 kfree(elog->buffer); 136 kfree(elog); 137 } 138 139 static struct attribute *elog_default_attrs[] = { 140 &id_attribute.attr, 141 &type_attribute.attr, 142 &ack_attribute.attr, 143 NULL, 144 }; 145 146 static struct kobj_type elog_ktype = { 147 .sysfs_ops = &elog_sysfs_ops, 148 .release = &elog_release, 149 .default_attrs = elog_default_attrs, 150 }; 151 152 /* Maximum size of a single log on FSP is 16KB */ 153 #define OPAL_MAX_ERRLOG_SIZE 16384 154 155 static ssize_t raw_attr_read(struct file *filep, struct kobject *kobj, 156 struct bin_attribute *bin_attr, 157 char *buffer, loff_t pos, size_t count) 158 { 159 int opal_rc; 160 161 struct elog_obj *elog = to_elog_obj(kobj); 162 163 /* We may have had an error reading before, so let's retry */ 164 if (!elog->buffer) { 165 elog->buffer = kzalloc(elog->size, GFP_KERNEL); 166 if (!elog->buffer) 167 return -EIO; 168 169 opal_rc = opal_read_elog(__pa(elog->buffer), 170 elog->size, elog->id); 171 if (opal_rc != OPAL_SUCCESS) { 172 pr_err("ELOG: log read failed for log-id=%llx\n", 173 elog->id); 174 kfree(elog->buffer); 175 elog->buffer = NULL; 176 return -EIO; 177 } 178 } 179 180 memcpy(buffer, elog->buffer + pos, count); 181 182 return count; 183 } 184 185 static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) 186 { 187 struct elog_obj *elog; 188 int rc; 189 190 elog = kzalloc(sizeof(*elog), GFP_KERNEL); 191 if (!elog) 192 return NULL; 193 194 elog->kobj.kset = elog_kset; 195 196 kobject_init(&elog->kobj, &elog_ktype); 197 198 sysfs_bin_attr_init(&elog->raw_attr); 199 200 elog->raw_attr.attr.name = "raw"; 201 elog->raw_attr.attr.mode = 0400; 202 elog->raw_attr.size = size; 203 elog->raw_attr.read = raw_attr_read; 204 205 elog->id = id; 206 elog->size = size; 207 elog->type = type; 208 209 elog->buffer = kzalloc(elog->size, GFP_KERNEL); 210 211 if (elog->buffer) { 212 rc = opal_read_elog(__pa(elog->buffer), 213 elog->size, elog->id); 214 if (rc != OPAL_SUCCESS) { 215 pr_err("ELOG: log read failed for log-id=%llx\n", 216 elog->id); 217 kfree(elog->buffer); 218 elog->buffer = NULL; 219 } 220 } 221 222 rc = kobject_add(&elog->kobj, NULL, "0x%llx", id); 223 if (rc) { 224 kobject_put(&elog->kobj); 225 return NULL; 226 } 227 228 rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr); 229 if (rc) { 230 kobject_put(&elog->kobj); 231 return NULL; 232 } 233 234 kobject_uevent(&elog->kobj, KOBJ_ADD); 235 236 return elog; 237 } 238 239 static void elog_work_fn(struct work_struct *work) 240 { 241 __be64 size; 242 __be64 id; 243 __be64 type; 244 uint64_t elog_size; 245 uint64_t log_id; 246 uint64_t elog_type; 247 int rc; 248 char name[2+16+1]; 249 250 rc = opal_get_elog_size(&id, &size, &type); 251 if (rc != OPAL_SUCCESS) { 252 pr_err("ELOG: Opal log read failed\n"); 253 return; 254 } 255 256 elog_size = be64_to_cpu(size); 257 log_id = be64_to_cpu(id); 258 elog_type = be64_to_cpu(type); 259 260 BUG_ON(elog_size > OPAL_MAX_ERRLOG_SIZE); 261 262 if (elog_size >= OPAL_MAX_ERRLOG_SIZE) 263 elog_size = OPAL_MAX_ERRLOG_SIZE; 264 265 sprintf(name, "0x%llx", log_id); 266 267 /* we may get notified twice, let's handle 268 * that gracefully and not create two conflicting 269 * entries. 270 */ 271 if (kset_find_obj(elog_kset, name)) 272 return; 273 274 create_elog_obj(log_id, elog_size, elog_type); 275 } 276 277 static DECLARE_WORK(elog_work, elog_work_fn); 278 279 static int elog_event(struct notifier_block *nb, 280 unsigned long events, void *change) 281 { 282 /* check for error log event */ 283 if (events & OPAL_EVENT_ERROR_LOG_AVAIL) 284 schedule_work(&elog_work); 285 return 0; 286 } 287 288 static struct notifier_block elog_nb = { 289 .notifier_call = elog_event, 290 .next = NULL, 291 .priority = 0 292 }; 293 294 int __init opal_elog_init(void) 295 { 296 int rc = 0; 297 298 elog_kset = kset_create_and_add("elog", NULL, opal_kobj); 299 if (!elog_kset) { 300 pr_warn("%s: failed to create elog kset\n", __func__); 301 return -1; 302 } 303 304 rc = opal_notifier_register(&elog_nb); 305 if (rc) { 306 pr_err("%s: Can't register OPAL event notifier (%d)\n", 307 __func__, rc); 308 return rc; 309 } 310 311 /* We are now ready to pull error logs from opal. */ 312 opal_resend_pending_logs(); 313 314 return 0; 315 } 316