[PATCH] s390: export ipl device parameters
Sysfs interface to export ipl device parameters. Dependent on the ipl type the interface will look like this: - ccw ipl: /sys/firmware/ipl/device /ipl_type - fcp ipl: /sys/firmware/ipl/binary_parameter /bootprog /br_lba /device /ipl_type /lun /scp_data /wwpn - otherwise (unknown that is): /sys/firmware/ipl/ipl_type Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
ed3cb6f039
commit
1e8e338325
@ -36,6 +36,7 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
@ -685,3 +686,188 @@ struct seq_operations cpuinfo_op = {
|
||||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
#define DEFINE_IPL_ATTR(_name, _format, _value) \
|
||||
static ssize_t ipl_##_name##_show(struct subsystem *subsys, \
|
||||
char *page) \
|
||||
{ \
|
||||
return sprintf(page, _format, _value); \
|
||||
} \
|
||||
static struct subsys_attribute ipl_##_name##_attr = \
|
||||
__ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL);
|
||||
|
||||
DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long)
|
||||
IPL_PARMBLOCK_START->fcp.wwpn);
|
||||
DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long)
|
||||
IPL_PARMBLOCK_START->fcp.lun);
|
||||
DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long)
|
||||
IPL_PARMBLOCK_START->fcp.bootprog);
|
||||
DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long)
|
||||
IPL_PARMBLOCK_START->fcp.br_lba);
|
||||
|
||||
enum ipl_type_type {
|
||||
ipl_type_unknown,
|
||||
ipl_type_ccw,
|
||||
ipl_type_fcp,
|
||||
};
|
||||
|
||||
static enum ipl_type_type
|
||||
get_ipl_type(void)
|
||||
{
|
||||
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
|
||||
|
||||
if (!IPL_DEVNO_VALID)
|
||||
return ipl_type_unknown;
|
||||
if (!IPL_PARMBLOCK_VALID)
|
||||
return ipl_type_ccw;
|
||||
if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION)
|
||||
return ipl_type_unknown;
|
||||
if (ipl->fcp.pbt != IPL_TYPE_FCP)
|
||||
return ipl_type_unknown;
|
||||
return ipl_type_fcp;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ipl_type_show(struct subsystem *subsys, char *page)
|
||||
{
|
||||
switch (get_ipl_type()) {
|
||||
case ipl_type_ccw:
|
||||
return sprintf(page, "ccw\n");
|
||||
case ipl_type_fcp:
|
||||
return sprintf(page, "fcp\n");
|
||||
default:
|
||||
return sprintf(page, "unknown\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type);
|
||||
|
||||
static ssize_t
|
||||
ipl_device_show(struct subsystem *subsys, char *page)
|
||||
{
|
||||
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
|
||||
|
||||
switch (get_ipl_type()) {
|
||||
case ipl_type_ccw:
|
||||
return sprintf(page, "0.0.%04x\n", ipl_devno);
|
||||
case ipl_type_fcp:
|
||||
return sprintf(page, "0.0.%04x\n", ipl->fcp.devno);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct subsys_attribute ipl_device_attr =
|
||||
__ATTR(device, S_IRUGO, ipl_device_show, NULL);
|
||||
|
||||
static struct attribute *ipl_fcp_attrs[] = {
|
||||
&ipl_type_attr.attr,
|
||||
&ipl_device_attr.attr,
|
||||
&ipl_wwpn_attr.attr,
|
||||
&ipl_lun_attr.attr,
|
||||
&ipl_bootprog_attr.attr,
|
||||
&ipl_br_lba_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ipl_fcp_attr_group = {
|
||||
.attrs = ipl_fcp_attrs,
|
||||
};
|
||||
|
||||
static struct attribute *ipl_ccw_attrs[] = {
|
||||
&ipl_type_attr.attr,
|
||||
&ipl_device_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ipl_ccw_attr_group = {
|
||||
.attrs = ipl_ccw_attrs,
|
||||
};
|
||||
|
||||
static struct attribute *ipl_unknown_attrs[] = {
|
||||
&ipl_type_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ipl_unknown_attr_group = {
|
||||
.attrs = ipl_unknown_attrs,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
unsigned int size = IPL_PARMBLOCK_SIZE;
|
||||
|
||||
if (off > size)
|
||||
return 0;
|
||||
if (off + count > size)
|
||||
count = size - off;
|
||||
|
||||
memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute ipl_parameter_attr = {
|
||||
.attr = {
|
||||
.name = "binary_parameter",
|
||||
.mode = S_IRUGO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = PAGE_SIZE,
|
||||
.read = &ipl_parameter_read,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len;
|
||||
void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data;
|
||||
|
||||
if (off > size)
|
||||
return 0;
|
||||
if (off + count > size)
|
||||
count = size - off;
|
||||
|
||||
memcpy(buf, scp_data + off, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute ipl_scp_data_attr = {
|
||||
.attr = {
|
||||
.name = "scp_data",
|
||||
.mode = S_IRUGO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = PAGE_SIZE,
|
||||
.read = &ipl_scp_data_read,
|
||||
};
|
||||
|
||||
static decl_subsys(ipl, NULL, NULL);
|
||||
|
||||
static int __init
|
||||
ipl_device_sysfs_register(void) {
|
||||
int rc;
|
||||
|
||||
rc = firmware_register(&ipl_subsys);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
switch (get_ipl_type()) {
|
||||
case ipl_type_ccw:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group);
|
||||
break;
|
||||
case ipl_type_fcp:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
|
||||
sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_parameter_attr);
|
||||
sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_scp_data_attr);
|
||||
break;
|
||||
default:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_unknown_attr_group);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(ipl_device_sysfs_register);
|
||||
|
Reference in New Issue
Block a user