mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
s390: nvme reipl
Populate sysfs and structs with reipl entries for nvme ipl type. This allows specifying a target nvme device when rebooting/reipling. Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
3737e8ee4f
commit
23a457b8d5
@ -136,6 +136,7 @@ static int reipl_capabilities = IPL_TYPE_UNKNOWN;
|
||||
|
||||
static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
|
||||
static struct ipl_parameter_block *reipl_block_fcp;
|
||||
static struct ipl_parameter_block *reipl_block_nvme;
|
||||
static struct ipl_parameter_block *reipl_block_ccw;
|
||||
static struct ipl_parameter_block *reipl_block_nss;
|
||||
static struct ipl_parameter_block *reipl_block_actual;
|
||||
@ -785,6 +786,93 @@ static struct attribute_group reipl_fcp_attr_group = {
|
||||
static struct kobj_attribute sys_reipl_fcp_clear_attr =
|
||||
__ATTR(clear, 0644, reipl_fcp_clear_show, reipl_fcp_clear_store);
|
||||
|
||||
/* NVME reipl device attributes */
|
||||
|
||||
static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
size_t size = reipl_block_nvme->nvme.scp_data_len;
|
||||
void *scp_data = reipl_block_nvme->nvme.scp_data;
|
||||
|
||||
return memory_read_from_buffer(buf, count, &off, scp_data, size);
|
||||
}
|
||||
|
||||
static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
size_t scpdata_len = count;
|
||||
size_t padding;
|
||||
|
||||
if (off)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(reipl_block_nvme->nvme.scp_data, buf, count);
|
||||
if (scpdata_len % 8) {
|
||||
padding = 8 - (scpdata_len % 8);
|
||||
memset(reipl_block_nvme->nvme.scp_data + scpdata_len,
|
||||
0, padding);
|
||||
scpdata_len += padding;
|
||||
}
|
||||
|
||||
reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
|
||||
reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
|
||||
reipl_block_nvme->nvme.scp_data_len = scpdata_len;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute sys_reipl_nvme_scp_data_attr =
|
||||
__BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
|
||||
reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
|
||||
|
||||
static struct bin_attribute *reipl_nvme_bin_attrs[] = {
|
||||
&sys_reipl_nvme_scp_data_attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
|
||||
reipl_block_nvme->nvme.fid);
|
||||
DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
|
||||
reipl_block_nvme->nvme.nsid);
|
||||
DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
|
||||
reipl_block_nvme->nvme.bootprog);
|
||||
DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
|
||||
reipl_block_nvme->nvme.br_lba);
|
||||
|
||||
/* nvme wrapper */
|
||||
static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *page)
|
||||
{
|
||||
return reipl_generic_loadparm_show(reipl_block_nvme, page);
|
||||
}
|
||||
|
||||
static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return reipl_generic_loadparm_store(reipl_block_nvme, buf, len);
|
||||
}
|
||||
|
||||
static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
|
||||
__ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
|
||||
reipl_nvme_loadparm_store);
|
||||
|
||||
static struct attribute *reipl_nvme_attrs[] = {
|
||||
&sys_reipl_nvme_fid_attr.attr,
|
||||
&sys_reipl_nvme_nsid_attr.attr,
|
||||
&sys_reipl_nvme_bootprog_attr.attr,
|
||||
&sys_reipl_nvme_br_lba_attr.attr,
|
||||
&sys_reipl_nvme_loadparm_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group reipl_nvme_attr_group = {
|
||||
.attrs = reipl_nvme_attrs,
|
||||
.bin_attrs = reipl_nvme_bin_attrs
|
||||
};
|
||||
|
||||
/* CCW reipl device attributes */
|
||||
DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
|
||||
|
||||
@ -949,6 +1037,9 @@ static int reipl_set_type(enum ipl_type type)
|
||||
case IPL_TYPE_FCP:
|
||||
reipl_block_actual = reipl_block_fcp;
|
||||
break;
|
||||
case IPL_TYPE_NVME:
|
||||
reipl_block_actual = reipl_block_nvme;
|
||||
break;
|
||||
case IPL_TYPE_NSS:
|
||||
reipl_block_actual = reipl_block_nss;
|
||||
break;
|
||||
@ -975,6 +1066,8 @@ static ssize_t reipl_type_store(struct kobject *kobj,
|
||||
rc = reipl_set_type(IPL_TYPE_CCW);
|
||||
else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
|
||||
rc = reipl_set_type(IPL_TYPE_FCP);
|
||||
else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
|
||||
rc = reipl_set_type(IPL_TYPE_NVME);
|
||||
else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
|
||||
rc = reipl_set_type(IPL_TYPE_NSS);
|
||||
return (rc != 0) ? rc : len;
|
||||
@ -985,6 +1078,7 @@ static struct kobj_attribute reipl_type_attr =
|
||||
|
||||
static struct kset *reipl_kset;
|
||||
static struct kset *reipl_fcp_kset;
|
||||
static struct kset *reipl_nvme_kset;
|
||||
|
||||
static void __reipl_run(void *unused)
|
||||
{
|
||||
@ -1003,11 +1097,14 @@ static void __reipl_run(void *unused)
|
||||
else
|
||||
diag308(DIAG308_LOAD_NORMAL, NULL);
|
||||
break;
|
||||
case IPL_TYPE_NVME:
|
||||
diag308(DIAG308_SET, reipl_block_nvme);
|
||||
diag308(DIAG308_LOAD_CLEAR, NULL);
|
||||
break;
|
||||
case IPL_TYPE_NSS:
|
||||
diag308(DIAG308_SET, reipl_block_nss);
|
||||
diag308(DIAG308_LOAD_CLEAR, NULL);
|
||||
break;
|
||||
case IPL_TYPE_NVME:
|
||||
case IPL_TYPE_UNKNOWN:
|
||||
diag308(DIAG308_LOAD_CLEAR, NULL);
|
||||
break;
|
||||
@ -1152,6 +1249,49 @@ static int __init reipl_fcp_init(void)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init reipl_nvme_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
|
||||
if (!reipl_block_nvme)
|
||||
return -ENOMEM;
|
||||
|
||||
/* sysfs: create kset for mixing attr group and bin attrs */
|
||||
reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL,
|
||||
&reipl_kset->kobj);
|
||||
if (!reipl_nvme_kset) {
|
||||
free_page((unsigned long) reipl_block_nvme);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
|
||||
if (rc) {
|
||||
kset_unregister(reipl_nvme_kset);
|
||||
free_page((unsigned long) reipl_block_nvme);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ipl_info.type == IPL_TYPE_NVME) {
|
||||
memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block));
|
||||
/*
|
||||
* Fix loadparm: There are systems where the (SCSI) LOADPARM
|
||||
* is invalid in the IPL parameter block, so take it
|
||||
* always from sclp_ipl_info.
|
||||
*/
|
||||
memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm,
|
||||
LOADPARM_LEN);
|
||||
} else {
|
||||
reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN;
|
||||
reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
|
||||
reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
|
||||
reipl_block_nvme->nvme.pbt = IPL_PBT_NVME;
|
||||
reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL;
|
||||
}
|
||||
reipl_capabilities |= IPL_TYPE_NVME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init reipl_type_init(void)
|
||||
{
|
||||
enum ipl_type reipl_type = ipl_info.type;
|
||||
@ -1167,6 +1307,9 @@ static int __init reipl_type_init(void)
|
||||
if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
|
||||
memcpy(reipl_block_fcp, reipl_block, size);
|
||||
reipl_type = IPL_TYPE_FCP;
|
||||
} else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) {
|
||||
memcpy(reipl_block_nvme, reipl_block, size);
|
||||
reipl_type = IPL_TYPE_NVME;
|
||||
} else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
|
||||
memcpy(reipl_block_ccw, reipl_block, size);
|
||||
reipl_type = IPL_TYPE_CCW;
|
||||
@ -1191,6 +1334,9 @@ static int __init reipl_init(void)
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = reipl_fcp_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = reipl_nvme_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = reipl_nss_init();
|
||||
|
Loading…
Reference in New Issue
Block a user