1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PowerNV OPAL Dump Interface 4 * 5 * Copyright 2013,2014 IBM Corp. 6 */ 7 8 #include <linux/kobject.h> 9 #include <linux/mm.h> 10 #include <linux/slab.h> 11 #include <linux/vmalloc.h> 12 #include <linux/pagemap.h> 13 #include <linux/delay.h> 14 #include <linux/interrupt.h> 15 16 #include <asm/opal.h> 17 18 #define DUMP_TYPE_FSP 0x01 19 20 struct dump_obj { 21 struct kobject kobj; 22 struct bin_attribute dump_attr; 23 uint32_t id; /* becomes object name */ 24 uint32_t type; 25 uint32_t size; 26 char *buffer; 27 }; 28 #define to_dump_obj(x) container_of(x, struct dump_obj, kobj) 29 30 struct dump_attribute { 31 struct attribute attr; 32 ssize_t (*show)(struct dump_obj *dump, struct dump_attribute *attr, 33 char *buf); 34 ssize_t (*store)(struct dump_obj *dump, struct dump_attribute *attr, 35 const char *buf, size_t count); 36 }; 37 #define to_dump_attr(x) container_of(x, struct dump_attribute, attr) 38 39 static ssize_t dump_id_show(struct dump_obj *dump_obj, 40 struct dump_attribute *attr, 41 char *buf) 42 { 43 return sprintf(buf, "0x%x\n", dump_obj->id); 44 } 45 46 static const char* dump_type_to_string(uint32_t type) 47 { 48 switch (type) { 49 case 0x01: return "SP Dump"; 50 case 0x02: return "System/Platform Dump"; 51 case 0x03: return "SMA Dump"; 52 default: return "unknown"; 53 } 54 } 55 56 static ssize_t dump_type_show(struct dump_obj *dump_obj, 57 struct dump_attribute *attr, 58 char *buf) 59 { 60 61 return sprintf(buf, "0x%x %s\n", dump_obj->type, 62 dump_type_to_string(dump_obj->type)); 63 } 64 65 static ssize_t dump_ack_show(struct dump_obj *dump_obj, 66 struct dump_attribute *attr, 67 char *buf) 68 { 69 return sprintf(buf, "ack - acknowledge dump\n"); 70 } 71 72 /* 73 * Send acknowledgement to OPAL 74 */ 75 static int64_t dump_send_ack(uint32_t dump_id) 76 { 77 int rc; 78 79 rc = opal_dump_ack(dump_id); 80 if (rc) 81 pr_warn("%s: Failed to send ack to Dump ID 0x%x (%d)\n", 82 __func__, dump_id, rc); 83 return rc; 84 } 85 86 static ssize_t dump_ack_store(struct dump_obj *dump_obj, 87 struct dump_attribute *attr, 88 const char *buf, 89 size_t count) 90 { 91 dump_send_ack(dump_obj->id); 92 sysfs_remove_file_self(&dump_obj->kobj, &attr->attr); 93 kobject_put(&dump_obj->kobj); 94 return count; 95 } 96 97 /* Attributes of a dump 98 * The binary attribute of the dump itself is dynamic 99 * due to the dynamic size of the dump 100 */ 101 static struct dump_attribute id_attribute = 102 __ATTR(id, 0444, dump_id_show, NULL); 103 static struct dump_attribute type_attribute = 104 __ATTR(type, 0444, dump_type_show, NULL); 105 static struct dump_attribute ack_attribute = 106 __ATTR(acknowledge, 0660, dump_ack_show, dump_ack_store); 107 108 static ssize_t init_dump_show(struct dump_obj *dump_obj, 109 struct dump_attribute *attr, 110 char *buf) 111 { 112 return sprintf(buf, "1 - initiate Service Processor(FSP) dump\n"); 113 } 114 115 static int64_t dump_fips_init(uint8_t type) 116 { 117 int rc; 118 119 rc = opal_dump_init(type); 120 if (rc) 121 pr_warn("%s: Failed to initiate FSP dump (%d)\n", 122 __func__, rc); 123 return rc; 124 } 125 126 static ssize_t init_dump_store(struct dump_obj *dump_obj, 127 struct dump_attribute *attr, 128 const char *buf, 129 size_t count) 130 { 131 int rc; 132 133 rc = dump_fips_init(DUMP_TYPE_FSP); 134 if (rc == OPAL_SUCCESS) 135 pr_info("%s: Initiated FSP dump\n", __func__); 136 137 return count; 138 } 139 140 static struct dump_attribute initiate_attribute = 141 __ATTR(initiate_dump, 0600, init_dump_show, init_dump_store); 142 143 static struct attribute *initiate_attrs[] = { 144 &initiate_attribute.attr, 145 NULL, 146 }; 147 148 static struct attribute_group initiate_attr_group = { 149 .attrs = initiate_attrs, 150 }; 151 152 static struct kset *dump_kset; 153 154 static ssize_t dump_attr_show(struct kobject *kobj, 155 struct attribute *attr, 156 char *buf) 157 { 158 struct dump_attribute *attribute; 159 struct dump_obj *dump; 160 161 attribute = to_dump_attr(attr); 162 dump = to_dump_obj(kobj); 163 164 if (!attribute->show) 165 return -EIO; 166 167 return attribute->show(dump, attribute, buf); 168 } 169 170 static ssize_t dump_attr_store(struct kobject *kobj, 171 struct attribute *attr, 172 const char *buf, size_t len) 173 { 174 struct dump_attribute *attribute; 175 struct dump_obj *dump; 176 177 attribute = to_dump_attr(attr); 178 dump = to_dump_obj(kobj); 179 180 if (!attribute->store) 181 return -EIO; 182 183 return attribute->store(dump, attribute, buf, len); 184 } 185 186 static const struct sysfs_ops dump_sysfs_ops = { 187 .show = dump_attr_show, 188 .store = dump_attr_store, 189 }; 190 191 static void dump_release(struct kobject *kobj) 192 { 193 struct dump_obj *dump; 194 195 dump = to_dump_obj(kobj); 196 vfree(dump->buffer); 197 kfree(dump); 198 } 199 200 static struct attribute *dump_default_attrs[] = { 201 &id_attribute.attr, 202 &type_attribute.attr, 203 &ack_attribute.attr, 204 NULL, 205 }; 206 207 static struct kobj_type dump_ktype = { 208 .sysfs_ops = &dump_sysfs_ops, 209 .release = &dump_release, 210 .default_attrs = dump_default_attrs, 211 }; 212 213 static int64_t dump_read_info(uint32_t *dump_id, uint32_t *dump_size, uint32_t *dump_type) 214 { 215 __be32 id, size, type; 216 int rc; 217 218 type = cpu_to_be32(0xffffffff); 219 220 rc = opal_dump_info2(&id, &size, &type); 221 if (rc == OPAL_PARAMETER) 222 rc = opal_dump_info(&id, &size); 223 224 if (rc) { 225 pr_warn("%s: Failed to get dump info (%d)\n", 226 __func__, rc); 227 return rc; 228 } 229 230 *dump_id = be32_to_cpu(id); 231 *dump_size = be32_to_cpu(size); 232 *dump_type = be32_to_cpu(type); 233 234 return rc; 235 } 236 237 static int64_t dump_read_data(struct dump_obj *dump) 238 { 239 struct opal_sg_list *list; 240 uint64_t addr; 241 int64_t rc; 242 243 /* Allocate memory */ 244 dump->buffer = vzalloc(PAGE_ALIGN(dump->size)); 245 if (!dump->buffer) { 246 pr_err("%s : Failed to allocate memory\n", __func__); 247 rc = -ENOMEM; 248 goto out; 249 } 250 251 /* Generate SG list */ 252 list = opal_vmalloc_to_sg_list(dump->buffer, dump->size); 253 if (!list) { 254 rc = -ENOMEM; 255 goto out; 256 } 257 258 /* First entry address */ 259 addr = __pa(list); 260 261 /* Fetch data */ 262 rc = OPAL_BUSY_EVENT; 263 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { 264 rc = opal_dump_read(dump->id, addr); 265 if (rc == OPAL_BUSY_EVENT) { 266 opal_poll_events(NULL); 267 msleep(20); 268 } 269 } 270 271 if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL) 272 pr_warn("%s: Extract dump failed for ID 0x%x\n", 273 __func__, dump->id); 274 275 /* Free SG list */ 276 opal_free_sg_list(list); 277 278 out: 279 return rc; 280 } 281 282 static ssize_t dump_attr_read(struct file *filep, struct kobject *kobj, 283 struct bin_attribute *bin_attr, 284 char *buffer, loff_t pos, size_t count) 285 { 286 ssize_t rc; 287 288 struct dump_obj *dump = to_dump_obj(kobj); 289 290 if (!dump->buffer) { 291 rc = dump_read_data(dump); 292 293 if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL) { 294 vfree(dump->buffer); 295 dump->buffer = NULL; 296 297 return -EIO; 298 } 299 if (rc == OPAL_PARTIAL) { 300 /* On a partial read, we just return EIO 301 * and rely on userspace to ask us to try 302 * again. 303 */ 304 pr_info("%s: Platform dump partially read. ID = 0x%x\n", 305 __func__, dump->id); 306 return -EIO; 307 } 308 } 309 310 memcpy(buffer, dump->buffer + pos, count); 311 312 /* You may think we could free the dump buffer now and retrieve 313 * it again later if needed, but due to current firmware limitation, 314 * that's not the case. So, once read into userspace once, 315 * we keep the dump around until it's acknowledged by userspace. 316 */ 317 318 return count; 319 } 320 321 static struct dump_obj *create_dump_obj(uint32_t id, size_t size, 322 uint32_t type) 323 { 324 struct dump_obj *dump; 325 int rc; 326 327 dump = kzalloc(sizeof(*dump), GFP_KERNEL); 328 if (!dump) 329 return NULL; 330 331 dump->kobj.kset = dump_kset; 332 333 kobject_init(&dump->kobj, &dump_ktype); 334 335 sysfs_bin_attr_init(&dump->dump_attr); 336 337 dump->dump_attr.attr.name = "dump"; 338 dump->dump_attr.attr.mode = 0400; 339 dump->dump_attr.size = size; 340 dump->dump_attr.read = dump_attr_read; 341 342 dump->id = id; 343 dump->size = size; 344 dump->type = type; 345 346 rc = kobject_add(&dump->kobj, NULL, "0x%x-0x%x", type, id); 347 if (rc) { 348 kobject_put(&dump->kobj); 349 return NULL; 350 } 351 352 rc = sysfs_create_bin_file(&dump->kobj, &dump->dump_attr); 353 if (rc) { 354 kobject_put(&dump->kobj); 355 return NULL; 356 } 357 358 pr_info("%s: New platform dump. ID = 0x%x Size %u\n", 359 __func__, dump->id, dump->size); 360 361 kobject_uevent(&dump->kobj, KOBJ_ADD); 362 363 return dump; 364 } 365 366 static irqreturn_t process_dump(int irq, void *data) 367 { 368 int rc; 369 uint32_t dump_id, dump_size, dump_type; 370 char name[22]; 371 struct kobject *kobj; 372 373 rc = dump_read_info(&dump_id, &dump_size, &dump_type); 374 if (rc != OPAL_SUCCESS) 375 return IRQ_HANDLED; 376 377 sprintf(name, "0x%x-0x%x", dump_type, dump_id); 378 379 /* we may get notified twice, let's handle 380 * that gracefully and not create two conflicting 381 * entries. 382 */ 383 kobj = kset_find_obj(dump_kset, name); 384 if (kobj) { 385 /* Drop reference added by kset_find_obj() */ 386 kobject_put(kobj); 387 return IRQ_HANDLED; 388 } 389 390 create_dump_obj(dump_id, dump_size, dump_type); 391 392 return IRQ_HANDLED; 393 } 394 395 void __init opal_platform_dump_init(void) 396 { 397 int rc; 398 int dump_irq; 399 400 /* ELOG not supported by firmware */ 401 if (!opal_check_token(OPAL_DUMP_READ)) 402 return; 403 404 dump_kset = kset_create_and_add("dump", NULL, opal_kobj); 405 if (!dump_kset) { 406 pr_warn("%s: Failed to create dump kset\n", __func__); 407 return; 408 } 409 410 rc = sysfs_create_group(&dump_kset->kobj, &initiate_attr_group); 411 if (rc) { 412 pr_warn("%s: Failed to create initiate dump attr group\n", 413 __func__); 414 kobject_put(&dump_kset->kobj); 415 return; 416 } 417 418 dump_irq = opal_event_request(ilog2(OPAL_EVENT_DUMP_AVAIL)); 419 if (!dump_irq) { 420 pr_err("%s: Can't register OPAL event irq (%d)\n", 421 __func__, dump_irq); 422 return; 423 } 424 425 rc = request_threaded_irq(dump_irq, NULL, process_dump, 426 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 427 "opal-dump", NULL); 428 if (rc) { 429 pr_err("%s: Can't request OPAL event irq (%d)\n", 430 __func__, rc); 431 return; 432 } 433 434 if (opal_check_token(OPAL_DUMP_RESEND)) 435 opal_dump_resend_notification(); 436 } 437