[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:
Heiko Carstens
2005-10-30 15:00:11 -08:00
committed by Linus Torvalds
parent ed3cb6f039
commit 1e8e338325
4 changed files with 367 additions and 7 deletions

View File

@ -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);