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

s390: nvme dump support

Add the nvme dump ipl type, associated data, and sysfs entries. This allows
booting into a stand alone dump environment that resides on an nvme device.

Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Jason J. Herne and committed by
Vasily Gorbik
d70e38cb 402e9228

+71 -1
+1
arch/s390/include/asm/ipl.h
··· 66 66 IPL_TYPE_FCP_DUMP = 8, 67 67 IPL_TYPE_NSS = 16, 68 68 IPL_TYPE_NVME = 32, 69 + IPL_TYPE_NVME_DUMP = 64, 69 70 }; 70 71 71 72 struct ipl_info
+70 -1
arch/s390/kernel/ipl.c
··· 40 40 #define IPL_FCP_STR "fcp" 41 41 #define IPL_FCP_DUMP_STR "fcp_dump" 42 42 #define IPL_NVME_STR "nvme" 43 + #define IPL_NVME_DUMP_STR "nvme_dump" 43 44 #define IPL_NSS_STR "nss" 44 45 45 46 #define DUMP_CCW_STR "ccw" 46 47 #define DUMP_FCP_STR "fcp" 48 + #define DUMP_NVME_STR "nvme" 47 49 #define DUMP_NONE_STR "none" 48 50 49 51 /* ··· 98 96 return IPL_NSS_STR; 99 97 case IPL_TYPE_NVME: 100 98 return IPL_NVME_STR; 99 + case IPL_TYPE_NVME_DUMP: 100 + return IPL_NVME_DUMP_STR; 101 101 case IPL_TYPE_UNKNOWN: 102 102 default: 103 103 return IPL_UNKNOWN_STR; ··· 110 106 DUMP_TYPE_NONE = 1, 111 107 DUMP_TYPE_CCW = 2, 112 108 DUMP_TYPE_FCP = 4, 109 + DUMP_TYPE_NVME = 8, 113 110 }; 114 111 115 112 static char *dump_type_str(enum dump_type type) ··· 122 117 return DUMP_CCW_STR; 123 118 case DUMP_TYPE_FCP: 124 119 return DUMP_FCP_STR; 120 + case DUMP_TYPE_NVME: 121 + return DUMP_NVME_STR; 125 122 default: 126 123 return NULL; 127 124 } ··· 151 144 static int dump_capabilities = DUMP_TYPE_NONE; 152 145 static enum dump_type dump_type = DUMP_TYPE_NONE; 153 146 static struct ipl_parameter_block *dump_block_fcp; 147 + static struct ipl_parameter_block *dump_block_nvme; 154 148 static struct ipl_parameter_block *dump_block_ccw; 155 149 156 150 static struct sclp_ipl_info sclp_ipl_info; ··· 274 266 else 275 267 return IPL_TYPE_FCP; 276 268 case IPL_PBT_NVME: 277 - return IPL_TYPE_NVME; 269 + if (ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP) 270 + return IPL_TYPE_NVME_DUMP; 271 + else 272 + return IPL_TYPE_NVME; 278 273 } 279 274 return IPL_TYPE_UNKNOWN; 280 275 } ··· 335 324 case IPL_TYPE_FCP_DUMP: 336 325 return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno); 337 326 case IPL_TYPE_NVME: 327 + case IPL_TYPE_NVME_DUMP: 338 328 return sprintf(page, "%08ux\n", ipl_block.nvme.fid); 339 329 default: 340 330 return 0; ··· 543 531 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group); 544 532 break; 545 533 case IPL_TYPE_NVME: 534 + case IPL_TYPE_NVME_DUMP: 546 535 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group); 547 536 break; 548 537 default: ··· 1122 1109 diag308(DIAG308_LOAD_CLEAR, NULL); 1123 1110 break; 1124 1111 case IPL_TYPE_FCP_DUMP: 1112 + case IPL_TYPE_NVME_DUMP: 1125 1113 break; 1126 1114 } 1127 1115 disabled_wait(); ··· 1396 1382 .attrs = dump_fcp_attrs, 1397 1383 }; 1398 1384 1385 + /* NVME dump device attributes */ 1386 + DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n", 1387 + dump_block_nvme->nvme.fid); 1388 + DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n", 1389 + dump_block_nvme->nvme.nsid); 1390 + DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n", 1391 + dump_block_nvme->nvme.bootprog); 1392 + DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n", 1393 + dump_block_nvme->nvme.br_lba); 1394 + 1395 + static struct attribute *dump_nvme_attrs[] = { 1396 + &sys_dump_nvme_fid_attr.attr, 1397 + &sys_dump_nvme_nsid_attr.attr, 1398 + &sys_dump_nvme_bootprog_attr.attr, 1399 + &sys_dump_nvme_br_lba_attr.attr, 1400 + NULL, 1401 + }; 1402 + 1403 + static struct attribute_group dump_nvme_attr_group = { 1404 + .name = IPL_NVME_STR, 1405 + .attrs = dump_nvme_attrs, 1406 + }; 1407 + 1399 1408 /* CCW dump device attributes */ 1400 1409 DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw); 1401 1410 ··· 1460 1423 rc = dump_set_type(DUMP_TYPE_CCW); 1461 1424 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0) 1462 1425 rc = dump_set_type(DUMP_TYPE_FCP); 1426 + else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0) 1427 + rc = dump_set_type(DUMP_TYPE_NVME); 1463 1428 return (rc != 0) ? rc : len; 1464 1429 } 1465 1430 ··· 1488 1449 break; 1489 1450 case DUMP_TYPE_FCP: 1490 1451 diag308_dump(dump_block_fcp); 1452 + break; 1453 + case DUMP_TYPE_NVME: 1454 + diag308_dump(dump_block_nvme); 1491 1455 break; 1492 1456 default: 1493 1457 break; ··· 1548 1506 return 0; 1549 1507 } 1550 1508 1509 + static int __init dump_nvme_init(void) 1510 + { 1511 + int rc; 1512 + 1513 + if (!sclp_ipl_info.has_dump) 1514 + return 0; /* LDIPL DUMP is not installed */ 1515 + dump_block_nvme = (void *) get_zeroed_page(GFP_KERNEL); 1516 + if (!dump_block_nvme) 1517 + return -ENOMEM; 1518 + rc = sysfs_create_group(&dump_kset->kobj, &dump_nvme_attr_group); 1519 + if (rc) { 1520 + free_page((unsigned long)dump_block_nvme); 1521 + return rc; 1522 + } 1523 + dump_block_nvme->hdr.len = IPL_BP_NVME_LEN; 1524 + dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION; 1525 + dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN; 1526 + dump_block_nvme->fcp.pbt = IPL_PBT_NVME; 1527 + dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP; 1528 + dump_capabilities |= DUMP_TYPE_NVME; 1529 + return 0; 1530 + } 1531 + 1551 1532 static int __init dump_init(void) 1552 1533 { 1553 1534 int rc; ··· 1587 1522 if (rc) 1588 1523 return rc; 1589 1524 rc = dump_fcp_init(); 1525 + if (rc) 1526 + return rc; 1527 + rc = dump_nvme_init(); 1590 1528 if (rc) 1591 1529 return rc; 1592 1530 dump_set_type(DUMP_TYPE_NONE); ··· 2024 1956 ipl_info.data.fcp.lun = ipl_block.fcp.lun; 2025 1957 break; 2026 1958 case IPL_TYPE_NVME: 1959 + case IPL_TYPE_NVME_DUMP: 2027 1960 ipl_info.data.nvme.fid = ipl_block.nvme.fid; 2028 1961 ipl_info.data.nvme.nsid = ipl_block.nvme.nsid; 2029 1962 break;