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: Sebastian Ott <sebott@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Sebastian Ott
2018-06-26 15:09:32 +02:00
committed by Martin Schwidefsky
parent 05b217f4c5
commit d4f5d79e97
4 changed files with 57 additions and 79 deletions

View File

@@ -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)