/*
 *  drivers/s390/char/sclp_ocf.c
 *    SCLP OCF communication parameters sysfs interface
 *
 *    Copyright IBM Corp. 2011
 *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
 */

#define KMSG_COMPONENT "sclp_ocf"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/kmod.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <asm/ebcdic.h>
#include <asm/sclp.h>

#include "sclp.h"

#define OCF_LENGTH_HMC_NETWORK 8UL
#define OCF_LENGTH_CPC_NAME 8UL

static char hmc_network[OCF_LENGTH_HMC_NETWORK + 1];
static char cpc_name[OCF_LENGTH_CPC_NAME + 1];

static DEFINE_SPINLOCK(sclp_ocf_lock);
static struct work_struct sclp_ocf_change_work;

static struct kset *ocf_kset;

static void sclp_ocf_change_notify(struct work_struct *work)
{
	kobject_uevent(&ocf_kset->kobj, KOBJ_CHANGE);
}

/* Handler for OCF event. Look for the CPC image name. */
static void sclp_ocf_handler(struct evbuf_header *evbuf)
{
	struct gds_vector *v;
	struct gds_subvector *sv, *netid, *cpc;
	size_t size;

	/* Find the 0x9f00 block. */
	v = sclp_find_gds_vector(evbuf + 1, (void *) evbuf + evbuf->length,
				 0x9f00);
	if (!v)
		return;
	/* Find the 0x9f22 block inside the 0x9f00 block. */
	v = sclp_find_gds_vector(v + 1, (void *) v + v->length, 0x9f22);
	if (!v)
		return;
	/* Find the 0x81 block inside the 0x9f22 block. */
	sv = sclp_find_gds_subvector(v + 1, (void *) v + v->length, 0x81);
	if (!sv)
		return;
	/* Find the 0x01 block inside the 0x81 block. */
	netid = sclp_find_gds_subvector(sv + 1, (void *) sv + sv->length, 1);
	/* Find the 0x02 block inside the 0x81 block. */
	cpc = sclp_find_gds_subvector(sv + 1, (void *) sv + sv->length, 2);
	/* Copy network name and cpc name. */
	spin_lock(&sclp_ocf_lock);
	if (netid) {
		size = min(OCF_LENGTH_HMC_NETWORK, (size_t) netid->length);
		memcpy(hmc_network, netid + 1, size);
		EBCASC(hmc_network, size);
		hmc_network[size] = 0;
	}
	if (cpc) {
		size = min(OCF_LENGTH_CPC_NAME, (size_t) cpc->length);
		memcpy(cpc_name, cpc + 1, size);
		EBCASC(cpc_name, size);
		cpc_name[size] = 0;
	}
	spin_unlock(&sclp_ocf_lock);
	schedule_work(&sclp_ocf_change_work);
}

static struct sclp_register sclp_ocf_event = {
	.receive_mask = EVTYP_OCF_MASK,
	.receiver_fn = sclp_ocf_handler,
};

static ssize_t cpc_name_show(struct kobject *kobj,
			     struct kobj_attribute *attr, char *page)
{
	int rc;

	spin_lock_irq(&sclp_ocf_lock);
	rc = snprintf(page, PAGE_SIZE, "%s\n", cpc_name);
	spin_unlock_irq(&sclp_ocf_lock);
	return rc;
}

static struct kobj_attribute cpc_name_attr =
	__ATTR(cpc_name, 0444, cpc_name_show, NULL);

static ssize_t hmc_network_show(struct kobject *kobj,
				struct kobj_attribute *attr, char *page)
{
	int rc;

	spin_lock_irq(&sclp_ocf_lock);
	rc = snprintf(page, PAGE_SIZE, "%s\n", hmc_network);
	spin_unlock_irq(&sclp_ocf_lock);
	return rc;
}

static struct kobj_attribute hmc_network_attr =
	__ATTR(hmc_network, 0444, hmc_network_show, NULL);

static struct attribute *ocf_attrs[] = {
	&cpc_name_attr.attr,
	&hmc_network_attr.attr,
	NULL,
};

static struct attribute_group ocf_attr_group = {
	.attrs = ocf_attrs,
};

static int __init ocf_init(void)
{
	int rc;

	INIT_WORK(&sclp_ocf_change_work, sclp_ocf_change_notify);
	ocf_kset = kset_create_and_add("ocf", NULL, firmware_kobj);
	if (!ocf_kset)
		return -ENOMEM;

	rc = sysfs_create_group(&ocf_kset->kobj, &ocf_attr_group);
	if (rc) {
		kset_unregister(ocf_kset);
		return rc;
	}

	return sclp_register(&sclp_ocf_event);
}

device_initcall(ocf_init);
