Commit 826b6a0f authored by Prarit Bhargava's avatar Prarit Bhargava Committed by Greg Kroah-Hartman
Browse files

staging: unisys: unify channel attributes into visorbus_main.c



The code in channel_attr.[ch] only creates sysfs files and is called
only in visorbus_main.c.  This code should be unified into
visorbus_main.c.   There are some functions that have been made static.

Signed-off-by: default avatarPrarit Bhargava <prarit@redhat.com>
Signed-off-by: default avatarBenjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a9a7c767
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

obj-$(CONFIG_UNISYS_VISORBUS)	+= visorbus.o

visorbus-y := visorbus_main.o devmajorminor_attr.o channel_attr.o
visorbus-y := visorbus_main.o devmajorminor_attr.o
visorbus-y	+= visorchannel_funcs.o

ccflags-y += -Idrivers/staging/unisys/include
+0 −227
Original line number Diff line number Diff line
/* channel_attr.c
 *
 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */

/* Implement publishing of channel attributes under:
 *
 *     /sys/bus/visorbus<x>/dev<y>/channel
 *
 */

#include "channel_attr.h"
#define CURRENT_FILE_PC VISOR_BUS_PC_channel_attr_c
#define to_channel_attr(_attr) \
	container_of(_attr, struct channel_attribute, attr)
#define to_visor_device_from_kobjchannel(obj) \
	container_of(obj, struct visor_device, kobjchannel)

struct channel_attribute {
	struct attribute attr;
	 ssize_t (*show)(struct visor_device*, char *buf);
	 ssize_t (*store)(struct visor_device*, const char *buf, size_t count);
};

/* begin implementation of specific channel attributes to appear under
* /sys/bus/visorbus<x>/dev<y>/channel
*/
static ssize_t devicechannel_attr_physaddr(struct visor_device *dev, char *buf)
{
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%Lx\n",
			visorchannel_get_physaddr(dev->visorchannel));
}

static ssize_t devicechannel_attr_nbytes(struct visor_device *dev, char *buf)
{
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%lx\n",
			visorchannel_get_nbytes(dev->visorchannel));
}

static ssize_t devicechannel_attr_clientpartition(struct visor_device *dev,
						  char *buf) {
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%Lx\n",
			visorchannel_get_clientpartition(dev->visorchannel));
}

static ssize_t devicechannel_attr_typeguid(struct visor_device *dev, char *buf)
{
	char s[99];

	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "%s\n",
			visorchannel_id(dev->visorchannel, s));
}

static ssize_t devicechannel_attr_zoneguid(struct visor_device *dev, char *buf)
{
	char s[99];

	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "%s\n",
			visorchannel_zoneid(dev->visorchannel, s));
}

static ssize_t devicechannel_attr_typename(struct visor_device *dev, char *buf)
{
	int i = 0;
	struct bus_type *xbus = dev->device.bus;
	struct device_driver *xdrv = dev->device.driver;
	struct visor_driver *drv = NULL;

	if (!dev->visorchannel || !xbus || !xdrv)
		return 0;
	i = xbus->match(&dev->device, xdrv);
	if (!i)
		return 0;
	drv = to_visor_driver(xdrv);
	return snprintf(buf, PAGE_SIZE, "%s\n", drv->channel_types[i - 1].name);
}

static ssize_t devicechannel_attr_dump(struct visor_device *dev, char *buf)
{
	int count = 0;
/* TODO: replace this with debugfs code
	struct seq_file *m = NULL;
	if (dev->visorchannel == NULL)
		return 0;
	m = visor_seq_file_new_buffer(buf, PAGE_SIZE - 1);
	if (m == NULL)
		return 0;
	visorchannel_debug(dev->visorchannel, 1, m, 0);
	count = m->count;
	visor_seq_file_done_buffer(m);
	m = NULL;
*/
	return count;
}

static struct channel_attribute all_channel_attrs[] = {
	__ATTR(physaddr, S_IRUGO,
	       devicechannel_attr_physaddr, NULL),
	__ATTR(nbytes, S_IRUGO,
	       devicechannel_attr_nbytes, NULL),
	__ATTR(clientpartition, S_IRUGO,
	       devicechannel_attr_clientpartition, NULL),
	__ATTR(typeguid, S_IRUGO,
	       devicechannel_attr_typeguid, NULL),
	__ATTR(zoneguid, S_IRUGO,
	       devicechannel_attr_zoneguid, NULL),
	__ATTR(typename, S_IRUGO,
	       devicechannel_attr_typename, NULL),
	__ATTR(dump, S_IRUGO,
	       devicechannel_attr_dump, NULL),
};

/* end implementation of specific channel attributes */

static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
				 char *buf)
{
	struct channel_attribute *channel_attr = to_channel_attr(attr);
	struct visor_device *dev = to_visor_device_from_kobjchannel(kobj);
	ssize_t ret = 0;

	if (channel_attr->show)
		ret = channel_attr->show(dev, buf);
	return ret;
}

static ssize_t channel_attr_store(struct kobject *kobj, struct attribute *attr,
				  const char *buf, size_t count)
{
	struct channel_attribute *channel_attr = to_channel_attr(attr);
	struct visor_device *dev = to_visor_device_from_kobjchannel(kobj);
	ssize_t ret = 0;

	if (channel_attr->store)
		ret = channel_attr->store(dev, buf, count);
	return ret;
}

static int channel_create_file(struct visor_device *dev,
			       struct channel_attribute *attr)
{
	return sysfs_create_file(&dev->kobjchannel, &attr->attr);
}

static void channel_remove_file(struct visor_device *dev,
				struct channel_attribute *attr)
{
	sysfs_remove_file(&dev->kobjchannel, &attr->attr);
}

static const struct sysfs_ops channel_sysfs_ops = {
	.show = channel_attr_show,
	.store = channel_attr_store,
};

static struct kobj_type channel_kobj_type = {
	.sysfs_ops = &channel_sysfs_ops
};

int register_channel_attributes(struct visor_device *dev)
{
	int rc = 0, i = 0, x = 0;

	if (dev->kobjchannel.parent)
		goto away;	/* already registered */
	x = kobject_init_and_add(&dev->kobjchannel, &channel_kobj_type,
				 &dev->device.kobj, "channel");
	if (x < 0) {
		rc = x;
		goto away;
	}

	kobject_uevent(&dev->kobjchannel, KOBJ_ADD);

	for (i = 0;
	     i < sizeof(all_channel_attrs) / sizeof(struct channel_attribute);
	     i++)
		x = channel_create_file(dev, &all_channel_attrs[i]);
	if (x < 0) {
		while (--i >= 0)
			channel_remove_file(dev, &all_channel_attrs[i]);
		kobject_del(&dev->kobjchannel);
		kobject_put(&dev->kobjchannel);
		rc = x;
		goto away;
	}
away:
	return rc;
}

void unregister_channel_attributes(struct visor_device *dev)
{
	int i = 0;

	if (!dev->kobjchannel.parent)
		return;		/* already unregistered */
	for (i = 0;
	     i < sizeof(all_channel_attrs) / sizeof(struct channel_attribute);
	     i++)
		channel_remove_file(dev, &all_channel_attrs[i]);

	kobject_del(&dev->kobjchannel);
	kobject_put(&dev->kobjchannel);
	dev->kobjchannel.parent = NULL;
}
+0 −27
Original line number Diff line number Diff line
/* channel_attr.h
 *
 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */

#ifndef __CHANNEL_ATTR_H__
#define __CHANNEL_ATTR_H__

#include "visorbus.h"		/* just to get visor_device declaration */
#include "timskmod.h"

int register_channel_attributes(struct visor_device *dev);
void unregister_channel_attributes(struct visor_device *dev);

#endif
+208 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@

#include "visorbus_private.h"
#include "timskmod.h"
#include "channel_attr.h"
#include "devmajorminor_attr.h"
#include "periodic_work.h"
#include "vbuschannel.h"
@@ -200,6 +199,214 @@ visorbus_release_device(struct device *xdev)
	kfree(dev);
}

/* Implement publishing of channel attributes under:
 *
 *     /sys/bus/visorbus<x>/dev<y>/channel
 *
 */

#define to_channel_attr(_attr) \
	container_of(_attr, struct channel_attribute, attr)
#define to_visor_device_from_kobjchannel(obj) \
	container_of(obj, struct visor_device, kobjchannel)

struct channel_attribute {
	struct attribute attr;
	 ssize_t (*show)(struct visor_device*, char *buf);
	 ssize_t (*store)(struct visor_device*, const char *buf, size_t count);
};

/* begin implementation of specific channel attributes to appear under
* /sys/bus/visorbus<x>/dev<y>/channel
*/
static ssize_t devicechannel_attr_physaddr(struct visor_device *dev, char *buf)
{
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%Lx\n",
			visorchannel_get_physaddr(dev->visorchannel));
}

static ssize_t devicechannel_attr_nbytes(struct visor_device *dev, char *buf)
{
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%lx\n",
			visorchannel_get_nbytes(dev->visorchannel));
}

static ssize_t devicechannel_attr_clientpartition(struct visor_device *dev,
						  char *buf) {
	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "0x%Lx\n",
			visorchannel_get_clientpartition(dev->visorchannel));
}

static ssize_t devicechannel_attr_typeguid(struct visor_device *dev, char *buf)
{
	char s[99];

	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "%s\n",
			visorchannel_id(dev->visorchannel, s));
}

static ssize_t devicechannel_attr_zoneguid(struct visor_device *dev, char *buf)
{
	char s[99];

	if (!dev->visorchannel)
		return 0;
	return snprintf(buf, PAGE_SIZE, "%s\n",
			visorchannel_zoneid(dev->visorchannel, s));
}

static ssize_t devicechannel_attr_typename(struct visor_device *dev, char *buf)
{
	int i = 0;
	struct bus_type *xbus = dev->device.bus;
	struct device_driver *xdrv = dev->device.driver;
	struct visor_driver *drv = NULL;

	if (!dev->visorchannel || !xbus || !xdrv)
		return 0;
	i = xbus->match(&dev->device, xdrv);
	if (!i)
		return 0;
	drv = to_visor_driver(xdrv);
	return snprintf(buf, PAGE_SIZE, "%s\n", drv->channel_types[i - 1].name);
}

static ssize_t devicechannel_attr_dump(struct visor_device *dev, char *buf)
{
	int count = 0;
/* TODO: replace this with debugfs code
	struct seq_file *m = NULL;
	if (dev->visorchannel == NULL)
		return 0;
	m = visor_seq_file_new_buffer(buf, PAGE_SIZE - 1);
	if (m == NULL)
		return 0;
	visorchannel_debug(dev->visorchannel, 1, m, 0);
	count = m->count;
	visor_seq_file_done_buffer(m);
	m = NULL;
*/
	return count;
}

static struct channel_attribute all_channel_attrs[] = {
	__ATTR(physaddr, S_IRUGO,
	       devicechannel_attr_physaddr, NULL),
	__ATTR(nbytes, S_IRUGO,
	       devicechannel_attr_nbytes, NULL),
	__ATTR(clientpartition, S_IRUGO,
	       devicechannel_attr_clientpartition, NULL),
	__ATTR(typeguid, S_IRUGO,
	       devicechannel_attr_typeguid, NULL),
	__ATTR(zoneguid, S_IRUGO,
	       devicechannel_attr_zoneguid, NULL),
	__ATTR(typename, S_IRUGO,
	       devicechannel_attr_typename, NULL),
	__ATTR(dump, S_IRUGO,
	       devicechannel_attr_dump, NULL),
};

/* end implementation of specific channel attributes */

static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
				 char *buf)
{
	struct channel_attribute *channel_attr = to_channel_attr(attr);
	struct visor_device *dev = to_visor_device_from_kobjchannel(kobj);
	ssize_t ret = 0;

	if (channel_attr->show)
		ret = channel_attr->show(dev, buf);
	return ret;
}

static ssize_t channel_attr_store(struct kobject *kobj, struct attribute *attr,
				  const char *buf, size_t count)
{
	struct channel_attribute *channel_attr = to_channel_attr(attr);
	struct visor_device *dev = to_visor_device_from_kobjchannel(kobj);
	ssize_t ret = 0;

	if (channel_attr->store)
		ret = channel_attr->store(dev, buf, count);
	return ret;
}

static int channel_create_file(struct visor_device *dev,
			       struct channel_attribute *attr)
{
	return sysfs_create_file(&dev->kobjchannel, &attr->attr);
}

static void channel_remove_file(struct visor_device *dev,
				struct channel_attribute *attr)
{
	sysfs_remove_file(&dev->kobjchannel, &attr->attr);
}

static const struct sysfs_ops channel_sysfs_ops = {
	.show = channel_attr_show,
	.store = channel_attr_store,
};

static struct kobj_type channel_kobj_type = {
	.sysfs_ops = &channel_sysfs_ops
};

int register_channel_attributes(struct visor_device *dev)
{
	int rc = 0, i = 0, x = 0;

	if (dev->kobjchannel.parent)
		goto away;	/* already registered */
	x = kobject_init_and_add(&dev->kobjchannel, &channel_kobj_type,
				 &dev->device.kobj, "channel");
	if (x < 0) {
		rc = x;
		goto away;
	}

	kobject_uevent(&dev->kobjchannel, KOBJ_ADD);

	for (i = 0;
	     i < sizeof(all_channel_attrs) / sizeof(struct channel_attribute);
	     i++)
		x = channel_create_file(dev, &all_channel_attrs[i]);
	if (x < 0) {
		while (--i >= 0)
			channel_remove_file(dev, &all_channel_attrs[i]);
		kobject_del(&dev->kobjchannel);
		kobject_put(&dev->kobjchannel);
		rc = x;
		goto away;
	}
away:
	return rc;
}

void unregister_channel_attributes(struct visor_device *dev)
{
	int i = 0;

	if (!dev->kobjchannel.parent)
		return;		/* already unregistered */
	for (i = 0;
	     i < sizeof(all_channel_attrs) / sizeof(struct channel_attribute);
	     i++)
		channel_remove_file(dev, &all_channel_attrs[i]);

	kobject_del(&dev->kobjchannel);
	kobject_put(&dev->kobjchannel);
	dev->kobjchannel.parent = NULL;
}
/*   This is actually something they forgot to put in the kernel.
 *   struct bus_type in the kernel SHOULD have a "busses" member, which
 *   should be treated similarly to the "devices" and "drivers" members.