// SPDX-License-Identifier: GPL-2.0
/*
 * Recognize and maintain s390 storage class memory.
 *
 * Copyright IBM Corp. 2012
 * Author(s): Sebastian Ott <sebott@linux.vnet.ibm.com>
 */

#include <linux/device.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
#include <asm/eadm.h>
#include "chsc.h"

static struct device *scm_root;

#define to_scm_dev(n) container_of(n, struct scm_device, dev)
#define	to_scm_drv(d) container_of(d, struct scm_driver, drv)

static int scmdev_probe(struct device *dev)
{
	struct scm_device *scmdev = to_scm_dev(dev);
	struct scm_driver *scmdrv = to_scm_drv(dev->driver);

	return scmdrv->probe ? scmdrv->probe(scmdev) : -ENODEV;
}

static void scmdev_remove(struct device *dev)
{
	struct scm_device *scmdev = to_scm_dev(dev);
	struct scm_driver *scmdrv = to_scm_drv(dev->driver);

	if (scmdrv->remove)
		scmdrv->remove(scmdev);
}

static int scmdev_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
	return add_uevent_var(env, "MODALIAS=scm:scmdev");
}

static const struct bus_type scm_bus_type = {
	.name  = "scm",
	.probe = scmdev_probe,
	.remove = scmdev_remove,
	.uevent = scmdev_uevent,
};

/**
 * scm_driver_register() - register a scm driver
 * @scmdrv: driver to be registered
 */
int scm_driver_register(struct scm_driver *scmdrv)
{
	struct device_driver *drv = &scmdrv->drv;

	drv->bus = &scm_bus_type;

	return driver_register(drv);
}
EXPORT_SYMBOL_GPL(scm_driver_register);

/**
 * scm_driver_unregister() - deregister a scm driver
 * @scmdrv: driver to be deregistered
 */
void scm_driver_unregister(struct scm_driver *scmdrv)
{
	driver_unregister(&scmdrv->drv);
}
EXPORT_SYMBOL_GPL(scm_driver_unregister);

void scm_irq_handler(struct aob *aob, blk_status_t error)
{
	struct aob_rq_header *aobrq = (void *) aob->request.data;
	struct scm_device *scmdev = aobrq->scmdev;
	struct scm_driver *scmdrv = to_scm_drv(scmdev->dev.driver);

	scmdrv->handler(scmdev, aobrq->data, error);
}
EXPORT_SYMBOL_GPL(scm_irq_handler);

#define scm_attr(name)							\
static ssize_t show_##name(struct device *dev,				\
	       struct device_attribute *attr, char *buf)		\
{									\
	struct scm_device *scmdev = to_scm_dev(dev);			\
	int ret;							\
									\
	device_lock(dev);						\
	ret = sysfs_emit(buf, "%u\n", scmdev->attrs.name);		\
	device_unlock(dev);						\
									\
	return ret;							\
}									\
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);

scm_attr(persistence);
scm_attr(oper_state);
scm_attr(data_state);
scm_attr(rank);
scm_attr(release);
scm_attr(res_id);

static struct attribute *scmdev_attrs[] = {
	&dev_attr_persistence.attr,
	&dev_attr_oper_state.attr,
	&dev_attr_data_state.attr,
	&dev_attr_rank.attr,
	&dev_attr_release.attr,
	&dev_attr_res_id.attr,
	NULL,
};

static struct attribute_group scmdev_attr_group = {
	.attrs = scmdev_attrs,
};

static const struct attribute_group *scmdev_attr_groups[] = {
	&scmdev_attr_group,
	NULL,
};

static void scmdev_release(struct device *dev)
{
	struct scm_device *scmdev = to_scm_dev(dev);

	kfree(scmdev);
}

static void scmdev_setup(struct scm_device *scmdev, struct sale *sale,
			 unsigned int size, unsigned int max_blk_count)
{
	dev_set_name(&scmdev->dev, "%016llx", (unsigned long long) sale->sa);
	scmdev->nr_max_block = max_blk_count;
	scmdev->address = sale->sa;
	scmdev->size = 1UL << size;
	scmdev->attrs.rank = sale->rank;
	scmdev->attrs.persistence = sale->p;
	scmdev->attrs.oper_state = sale->op_state;
	scmdev->attrs.data_state = sale->data_state;
	scmdev->attrs.rank = sale->rank;
	scmdev->attrs.release = sale->r;
	scmdev->attrs.res_id = sale->rid;
	scmdev->dev.parent = scm_root;
	scmdev->dev.bus = &scm_bus_type;
	scmdev->dev.release = scmdev_release;
	scmdev->dev.groups = scmdev_attr_groups;
}

/*
 * Check for state-changes, notify the driver and userspace.
 */
static void scmdev_update(struct scm_device *scmdev, struct sale *sale)
{
	struct scm_driver *scmdrv;
	bool changed;

	device_lock(&scmdev->dev);
	changed = scmdev->attrs.rank != sale->rank ||
		  scmdev->attrs.oper_state != sale->op_state;
	scmdev->attrs.rank = sale->rank;
	scmdev->attrs.oper_state = sale->op_state;
	if (!scmdev->dev.driver)
		goto out;
	scmdrv = to_scm_drv(scmdev->dev.driver);
	if (changed && scmdrv->notify)
		scmdrv->notify(scmdev, SCM_CHANGE);
out:
	device_unlock(&scmdev->dev);
	if (changed)
		kobject_uevent(&scmdev->dev.kobj, KOBJ_CHANGE);
}

static int check_address(struct device *dev, const void *data)
{
	struct scm_device *scmdev = to_scm_dev(dev);
	const struct sale *sale = data;

	return scmdev->address == sale->sa;
}

static struct scm_device *scmdev_find(struct sale *sale)
{
	struct device *dev;

	dev = bus_find_device(&scm_bus_type, NULL, sale, check_address);

	return dev ? to_scm_dev(dev) : NULL;
}

static int scm_add(struct chsc_scm_info *scm_info, size_t num)
{
	struct sale *sale, *scmal = scm_info->scmal;
	struct scm_device *scmdev;
	int ret;

	for (sale = scmal; sale < scmal + num; sale++) {
		scmdev = scmdev_find(sale);
		if (scmdev) {
			scmdev_update(scmdev, sale);
			/* Release reference from scm_find(). */
			put_device(&scmdev->dev);
			continue;
		}
		scmdev = kzalloc_obj(*scmdev);
		if (!scmdev)
			return -ENODEV;
		scmdev_setup(scmdev, sale, scm_info->is, scm_info->mbc);
		ret = device_register(&scmdev->dev);
		if (ret) {
			/* Release reference from device_initialize(). */
			put_device(&scmdev->dev);
			return ret;
		}
	}

	return 0;
}

int scm_update_information(void)
{
	struct chsc_scm_info *scm_info;
	u64 token = 0;
	size_t num;
	int ret;

	scm_info = (void *)__get_free_page(GFP_KERNEL);
	if (!scm_info)
		return -ENOMEM;

	do {
		ret = chsc_scm_info(scm_info, token);
		if (ret)
			break;

		num = (scm_info->response.length -
		       (offsetof(struct chsc_scm_info, scmal) -
			offsetof(struct chsc_scm_info, response))
		      ) / sizeof(struct sale);

		ret = scm_add(scm_info, num);
		if (ret)
			break;

		token = scm_info->restok;
	} while (token);

	free_page((unsigned long)scm_info);

	return ret;
}

static int scm_dev_avail(struct device *dev, void *unused)
{
	struct scm_driver *scmdrv = to_scm_drv(dev->driver);
	struct scm_device *scmdev = to_scm_dev(dev);

	if (dev->driver && scmdrv->notify)
		scmdrv->notify(scmdev, SCM_AVAIL);

	return 0;
}

int scm_process_availability_information(void)
{
	return bus_for_each_dev(&scm_bus_type, NULL, NULL, scm_dev_avail);
}

static int __init scm_init(void)
{
	int ret;

	ret = bus_register(&scm_bus_type);
	if (ret)
		return ret;

	scm_root = root_device_register("scm");
	if (IS_ERR(scm_root)) {
		bus_unregister(&scm_bus_type);
		return PTR_ERR(scm_root);
	}

	scm_update_information();
	return 0;
}
subsys_initcall_sync(scm_init);
