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

Commit d4f5d79e authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/css: reduce stsch calls



Both css_evaluate_new_subchannel and cio_validate_subchannel used
stsch and css_sch_is_valid to check for a valid device.

Reduce stsch calls during subchannel evaluation by re-using schib
data. Also the type/devno valid information is only checked once.

Signed-off-by: default avatarSebastian Ott <sebott@linux.ibm.com>
Reviewed-by: default avatarPeter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 05b217f4
Loading
Loading
Loading
Loading
+6 −59
Original line number Diff line number Diff line
@@ -526,64 +526,6 @@ int cio_disable_subchannel(struct subchannel *sch)
}
EXPORT_SYMBOL_GPL(cio_disable_subchannel);

/**
 * cio_validate_subchannel - basic validation of subchannel
 * @schid: subchannel id
 * @schib: subchannel information block to be filled out
 *
 * Check if subchannel is valid and should be used.
 * Return codes:
 *   0 on success
 *   -ENXIO for non-defined subchannels
 *   -ENODEV for invalid subchannels or blacklisted devices
 *   -EIO for subchannels in an invalid subchannel set
 */
int cio_validate_subchannel(struct subchannel_id schid, struct schib *schib)
{
	char dbf_txt[15];
	int ccode;
	int err;

	sprintf(dbf_txt, "valsch%x", schid.sch_no);
	CIO_TRACE_EVENT(4, dbf_txt);

	/*
	 * The first subchannel that is not-operational (ccode==3)
	 * indicates that there aren't any more devices available.
	 * If stsch gets an exception, it means the current subchannel set
	 * is not valid.
	 */
	ccode = stsch(schid, schib);
	if (ccode) {
		err = (ccode == 3) ? -ENXIO : ccode;
		goto out;
	}

	switch (schib->pmcw.st) {
	case SUBCHANNEL_TYPE_IO:
	case SUBCHANNEL_TYPE_MSG:
		if (!css_sch_is_valid(schib))
			err = -ENODEV;
		else if (is_blacklisted(schid.ssid, schib->pmcw.dev)) {
			CIO_MSG_EVENT(6, "Blacklisted device detected "
				      "at devno %04X, subchannel set %x\n",
				      schib->pmcw.dev, schid.ssid);
			err = -ENODEV;
		} else
			err = 0;
		break;
	default:
		err = 0;
	}
	if (err)
		goto out;

	CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
		      schid.ssid, schid.sch_no, schib->pmcw.st);
out:
	return err;
}

/*
 * do_cio_interrupt() handles all normal I/O device IRQ's
 */
@@ -707,6 +649,7 @@ struct subchannel *cio_probe_console(void)
{
	struct subchannel_id schid;
	struct subchannel *sch;
	struct schib schib;
	int sch_no, ret;

	sch_no = cio_get_console_sch_no();
@@ -716,7 +659,11 @@ struct subchannel *cio_probe_console(void)
	}
	init_subchannel_id(&schid);
	schid.sch_no = sch_no;
	sch = css_alloc_subchannel(schid);
	ret = stsch(schid, &schib);
	if (ret)
		return ERR_PTR(-ENODEV);

	sch = css_alloc_subchannel(schid, &schib);
	if (IS_ERR(sch))
		return sch;

+0 −1
Original line number Diff line number Diff line
@@ -119,7 +119,6 @@ DECLARE_PER_CPU(struct irb, cio_irb);

#define to_subchannel(n) container_of(n, struct subchannel, dev)

extern int cio_validate_subchannel(struct subchannel_id, struct schib *);
extern int cio_enable_subchannel(struct subchannel *, u32);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
+49 −18
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "css.h"
#include "cio.h"
#include "blacklist.h"
#include "cio_debug.h"
#include "ioasm.h"
#include "chsc.h"
@@ -168,13 +169,43 @@ static void css_subchannel_release(struct device *dev)
	kfree(sch);
}

struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
static int css_validate_subchannel(struct subchannel_id schid,
				   struct schib *schib)
{
	int err;

	switch (schib->pmcw.st) {
	case SUBCHANNEL_TYPE_IO:
	case SUBCHANNEL_TYPE_MSG:
		if (!css_sch_is_valid(schib))
			err = -ENODEV;
		else if (is_blacklisted(schid.ssid, schib->pmcw.dev)) {
			CIO_MSG_EVENT(6, "Blacklisted device detected "
				      "at devno %04X, subchannel set %x\n",
				      schib->pmcw.dev, schid.ssid);
			err = -ENODEV;
		} else
			err = 0;
		break;
	default:
		err = 0;
	}
	if (err)
		goto out;

	CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
		      schid.ssid, schid.sch_no, schib->pmcw.st);
out:
	return err;
}

struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
					struct schib *schib)
{
	struct subchannel *sch;
	struct schib schib;
	int ret;

	ret = cio_validate_subchannel(schid, &schib);
	ret = css_validate_subchannel(schid, schib);
	if (ret < 0)
		return ERR_PTR(ret);

@@ -183,8 +214,8 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
		return ERR_PTR(-ENOMEM);

	sch->schid = schid;
	sch->schib = schib;
	sch->st = schib.pmcw.st;
	sch->schib = *schib;
	sch->st = schib->pmcw.st;

	ret = css_sch_create_locks(sch);
	if (ret)
@@ -386,12 +417,12 @@ int css_register_subchannel(struct subchannel *sch)
	return ret;
}

static int css_probe_device(struct subchannel_id schid)
static int css_probe_device(struct subchannel_id schid, struct schib *schib)
{
	struct subchannel *sch;
	int ret;

	sch = css_alloc_subchannel(schid);
	sch = css_alloc_subchannel(schid, schib);
	if (IS_ERR(sch))
		return PTR_ERR(sch);

@@ -440,23 +471,23 @@ EXPORT_SYMBOL_GPL(css_sch_is_valid);
static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
{
	struct schib schib;
	int ccode;

	if (!slow) {
		/* Will be done on the slow path. */
		return -EAGAIN;
	}
	if (stsch(schid, &schib)) {
		/* Subchannel is not provided. */
		return -ENXIO;
	}
	if (!css_sch_is_valid(&schib)) {
		/* Unusable - ignore. */
		return 0;
	}
	CIO_MSG_EVENT(4, "event: sch 0.%x.%04x, new\n", schid.ssid,
		      schid.sch_no);
	/*
	 * The first subchannel that is not-operational (ccode==3)
	 * indicates that there aren't any more devices available.
	 * If stsch gets an exception, it means the current subchannel set
	 * is not valid.
	 */
	ccode = stsch(schid, &schib);
	if (ccode)
		return (ccode == 3) ? -ENXIO : ccode;

	return css_probe_device(schid);
	return css_probe_device(schid, &schib);
}

static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
+2 −1
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ extern void css_driver_unregister(struct css_driver *);

extern void css_sch_device_unregister(struct subchannel *);
extern int css_register_subchannel(struct subchannel *);
extern struct subchannel *css_alloc_subchannel(struct subchannel_id);
extern struct subchannel *css_alloc_subchannel(struct subchannel_id,
					       struct schib *schib);
extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
extern int max_ssid;