Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e9db9ea authored by Cornelia Huck's avatar Cornelia Huck Committed by Heiko Carstens
Browse files

[S390] cio: Introduce modalias for css bus.



Add modalias and subchannel type attributes for all subchannels.
I/O subchannel specific attributes are now created in
io_subchannel_probe(). modalias and subchannel type are also
added to the uevent for the css bus. Also make the css modalias
known.

Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent 0ae7a7b2
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
What:		/sys/bus/css/devices/.../type
Date:		March 2008
Contact:	Cornelia Huck <cornelia.huck@de.ibm.com>
		linux-s390@vger.kernel.org
Description:	Contains the subchannel type, as reported by the hardware.
		This attribute is present for all subchannel types.

What:		/sys/bus/css/devices/.../modalias
Date:		March 2008
Contact:	Cornelia Huck <cornelia.huck@de.ibm.com>
		linux-s390@vger.kernel.org
Description:	Contains the module alias as reported with uevents.
		It is of the format css:t<type> and present for all
		subchannel types.

What:		/sys/bus/css/drivers/io_subchannel/.../chpids
Date:		December 2002
Contact:	Cornelia Huck <cornelia.huck@de.ibm.com>
		linux-s390@vger.kernel.org
Description:	Contains the ids of the channel paths used by this
		subchannel, as reported by the channel subsystem
		during subchannel recognition.
		Note: This is an I/O-subchannel specific attribute.
Users:		s390-tools, HAL

What:		/sys/bus/css/drivers/io_subchannel/.../pimpampom
Date:		December 2002
Contact:	Cornelia Huck <cornelia.huck@de.ibm.com>
		linux-s390@vger.kernel.org
Description:	Contains the PIM/PAM/POM values, as reported by the
		channel subsystem when last queried by the common I/O
		layer (this implies that this attribute is not neccessarily
		in sync with the values current in the channel subsystem).
		Note: This is an I/O-subchannel specific attribute.
Users:		s390-tools, HAL
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <asm/chpid.h>
#include "chsc.h"
#include "schid.h"
+63 −6
Original line number Diff line number Diff line
@@ -2,8 +2,7 @@
 *  drivers/s390/cio/css.c
 *  driver for channel subsystem
 *
 *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
 *			 IBM Corporation
 *    Copyright IBM Corp. 2002,2008
 *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
 *		 Cornelia Huck (cornelia.huck@de.ibm.com)
 */
@@ -210,6 +209,41 @@ void css_update_ssd_info(struct subchannel *sch)
	}
}

static ssize_t type_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{
	struct subchannel *sch = to_subchannel(dev);

	return sprintf(buf, "%01x\n", sch->st);
}

static DEVICE_ATTR(type, 0444, type_show, NULL);

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
			     char *buf)
{
	struct subchannel *sch = to_subchannel(dev);

	return sprintf(buf, "css:t%01X\n", sch->st);
}

static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);

static struct attribute *subch_attrs[] = {
	&dev_attr_type.attr,
	&dev_attr_modalias.attr,
	NULL,
};

static struct attribute_group subch_attr_group = {
	.attrs = subch_attrs,
};

static struct attribute_group *default_subch_attr_groups[] = {
	&subch_attr_group,
	NULL,
};

static int css_register_subchannel(struct subchannel *sch)
{
	int ret;
@@ -218,15 +252,16 @@ static int css_register_subchannel(struct subchannel *sch)
	sch->dev.parent = &channel_subsystems[0]->device;
	sch->dev.bus = &css_bus_type;
	sch->dev.release = &css_subchannel_release;
	sch->dev.groups = subch_attr_groups;
	sch->dev.groups = default_subch_attr_groups;
	/*
	 * We don't want to generate uevents for I/O subchannels that don't
	 * have a working ccw device behind them since they will be
	 * unregistered before they can be used anyway, so we delay the add
	 * uevent until after device recognition was successful.
	 * Note that we suppress the uevent for all subchannel types;
	 * the subchannel driver can decide itself when it wants to inform
	 * userspace of its existence.
	 */
	if (!cio_is_console(sch->schid))
		/* Console is special, no need to suppress. */
	sch->dev.uevent_suppress = 1;
	css_update_ssd_info(sch);
	/* make it known to the system */
@@ -236,6 +271,15 @@ static int css_register_subchannel(struct subchannel *sch)
			      sch->schid.ssid, sch->schid.sch_no, ret);
		return ret;
	}
	if (!sch->driver) {
		/*
		 * No driver matched. Generate the uevent now so that
		 * a fitting driver module may be loaded based on the
		 * modalias.
		 */
		sch->dev.uevent_suppress = 0;
		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
	}
	return ret;
}

@@ -926,12 +970,25 @@ static void css_shutdown(struct device *dev)
		sch->driver->shutdown(sch);
}

static int css_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct subchannel *sch = to_subchannel(dev);
	int ret;

	ret = add_uevent_var(env, "ST=%01X", sch->st);
	if (ret)
		return ret;
	ret = add_uevent_var(env, "MODALIAS=css:t%01X", sch->st);
	return ret;
}

struct bus_type css_bus_type = {
	.name     = "css",
	.match    = css_bus_match,
	.probe    = css_probe,
	.remove   = css_remove,
	.shutdown = css_shutdown,
	.uevent   = css_uevent,
};

/**
+0 −2
Original line number Diff line number Diff line
@@ -143,6 +143,4 @@ int css_sch_is_valid(struct schib *);

extern struct workqueue_struct *slow_path_wq;
void css_wait_for_slow_path(void);

extern struct attribute_group *subch_attr_groups[];
#endif
+31 −16
Original line number Diff line number Diff line
@@ -585,19 +585,14 @@ static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
static DEVICE_ATTR(online, 0644, online_show, online_store);
static DEVICE_ATTR(availability, 0444, available_show, NULL);

static struct attribute * subch_attrs[] = {
static struct attribute *io_subchannel_attrs[] = {
	&dev_attr_chpids.attr,
	&dev_attr_pimpampom.attr,
	NULL,
};

static struct attribute_group subch_attr_group = {
	.attrs = subch_attrs,
};

struct attribute_group *subch_attr_groups[] = {
	&subch_attr_group,
	NULL,
static struct attribute_group io_subchannel_attr_group = {
	.attrs = io_subchannel_attrs,
};

static struct attribute * ccwdev_attrs[] = {
@@ -1157,11 +1152,21 @@ static int io_subchannel_probe(struct subchannel *sch)

	cdev = sch_get_cdev(sch);
	if (cdev) {
		rc = sysfs_create_group(&sch->dev.kobj,
					&io_subchannel_attr_group);
		if (rc)
			CIO_MSG_EVENT(0, "Failed to create io subchannel "
				      "attributes for subchannel "
				      "0.%x.%04x (rc=%d)\n",
				      sch->schid.ssid, sch->schid.sch_no, rc);
		/*
		 * This subchannel already has an associated ccw_device.
		 * Register it and exit. This happens for all early
		 * device, e.g. the console.
		 * Throw the delayed uevent for the subchannel, register
		 * the ccw_device and exit. This happens for all early
		 * devices, e.g. the console.
		 */
		sch->dev.uevent_suppress = 0;
		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
		cdev->dev.groups = ccwdev_attr_groups;
		device_initialize(&cdev->dev);
		ccw_device_register(cdev);
@@ -1184,11 +1189,17 @@ static int io_subchannel_probe(struct subchannel *sch)
	 */
	dev_id.devno = sch->schib.pmcw.dev;
	dev_id.ssid = sch->schid.ssid;
	rc = sysfs_create_group(&sch->dev.kobj,
				&io_subchannel_attr_group);
	if (rc)
		return rc;
	/* Allocate I/O subchannel private data. */
	sch->private = kzalloc(sizeof(struct io_subchannel_private),
			       GFP_KERNEL | GFP_DMA);
	if (!sch->private)
		return -ENOMEM;
	if (!sch->private) {
		rc = -ENOMEM;
		goto out_err;
	}
	cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
	if (!cdev)
		cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
@@ -1207,8 +1218,8 @@ static int io_subchannel_probe(struct subchannel *sch)
	}
	cdev = io_subchannel_create_ccwdev(sch);
	if (IS_ERR(cdev)) {
		kfree(sch->private);
		return PTR_ERR(cdev);
		rc = PTR_ERR(cdev);
		goto out_err;
	}
	rc = io_subchannel_recog(cdev, sch);
	if (rc) {
@@ -1217,9 +1228,12 @@ static int io_subchannel_probe(struct subchannel *sch)
		spin_unlock_irqrestore(sch->lock, flags);
		if (cdev->dev.release)
			cdev->dev.release(&cdev->dev);
		kfree(sch->private);
		goto out_err;
	}

	return 0;
out_err:
	kfree(sch->private);
	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
	return rc;
}

@@ -1240,6 +1254,7 @@ io_subchannel_remove (struct subchannel *sch)
	ccw_device_unregister(cdev);
	put_device(&cdev->dev);
	kfree(sch->private);
	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
	return 0;
}

Loading