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

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

[S390] cio: Cleanup crw interface.



Eliminate the need for the machine check handler to call into
the common I/O layer directly by introducing an interface to
register handlers for crws per rsc.

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 c820de39
Loading
Loading
Loading
Loading
+42 −7
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <asm/chpid.h>
#include <asm/sclp.h>

#include "../s390mach.h"
#include "cio.h"
#include "css.h"
#include "ioasm.h"
@@ -476,24 +477,52 @@ void *chp_get_chp_desc(struct chp_id chpid)

/**
 * chp_process_crw - process channel-path status change
 * @id: channel-path ID number
 * @status: non-zero if channel-path has become available, zero otherwise
 * @crw0: channel report-word to handler
 * @crw1: second channel-report word (always NULL)
 * @overflow: crw overflow indication
 *
 * Handle channel-report-words indicating that the status of a channel-path
 * has changed.
 */
void chp_process_crw(int id, int status)
static void chp_process_crw(struct crw *crw0, struct crw *crw1,
			    int overflow)
{
	struct chp_id chpid;

	if (overflow) {
		css_schedule_eval_all();
		return;
	}
	CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, "
		      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
		      crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
		      crw0->erc, crw0->rsid);
	/*
	 * Check for solicited machine checks. These are
	 * created by reset channel path and need not be
	 * handled here.
	 */
	if (crw0->slct) {
		CIO_CRW_EVENT(2, "solicited machine check for "
			      "channel path %02X\n", crw0->rsid);
		return;
	}
	chp_id_init(&chpid);
	chpid.id = id;
	if (status) {
	chpid.id = crw0->rsid;
	switch (crw0->erc) {
	case CRW_ERC_IPARM: /* Path has come. */
		if (!chp_is_registered(chpid))
			chp_new(chpid);
		chsc_chp_online(chpid);
	} else
		break;
	case CRW_ERC_PERRI: /* Path has gone. */
	case CRW_ERC_PERRN:
		chsc_chp_offline(chpid);
		break;
	default:
		CIO_CRW_EVENT(2, "Don't know how to handle erc=%x\n",
			      crw0->erc);
	}
}

int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data)
@@ -674,10 +703,16 @@ static int cfg_wait_idle(void)
static int __init chp_init(void)
{
	struct chp_id chpid;
	int ret;

	ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw);
	if (ret)
		return ret;
	chp_wq = create_singlethread_workqueue("cio_chp");
	if (!chp_wq)
	if (!chp_wq) {
		s390_unregister_crw_handler(CRW_RSC_CPATH);
		return -ENOMEM;
	}
	INIT_WORK(&cfg_work, cfg_func);
	init_waitqueue_head(&cfg_wait_queue);
	if (info_update())
+0 −1
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ int chp_get_status(struct chp_id chpid);
u8 chp_get_sch_opm(struct subchannel *sch);
int chp_is_registered(struct chp_id chpid);
void *chp_get_chp_desc(struct chp_id chpid);
void chp_process_crw(int id, int available);
void chp_remove_cmg_attr(struct channel_path *chp);
int chp_add_cmg_attr(struct channel_path *chp);
int chp_new(struct chp_id chpid);
+21 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <asm/cio.h>
#include <asm/chpid.h>

#include "../s390mach.h"
#include "css.h"
#include "cio.h"
#include "cio_debug.h"
@@ -372,10 +373,18 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area)
	}
}

void chsc_process_crw(void)
static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
{
	struct chsc_sei_area *sei_area;

	if (overflow) {
		css_schedule_eval_all();
		return;
	}
	CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, "
		      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
		      crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
		      crw0->erc, crw0->rsid);
	if (!sei_page)
		return;
	/* Access to sei_page is serialized through machine check handler
@@ -751,15 +760,23 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)

int __init chsc_alloc_sei_area(void)
{
	int ret;

	sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!sei_page)
	if (!sei_page) {
		CIO_MSG_EVENT(0, "Can't allocate page for processing of "
			      "chsc machine checks!\n");
	return (sei_page ? 0 : -ENOMEM);
		return -ENOMEM;
	}
	ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw);
	if (ret)
		kfree(sei_page);
	return ret;
}

void __init chsc_free_sei_area(void)
{
	s390_unregister_crw_handler(CRW_RSC_CSS);
	kfree(sei_page);
}

+0 −2
Original line number Diff line number Diff line
@@ -36,8 +36,6 @@ struct channel_path_desc {

struct channel_path;

extern void chsc_process_crw(void);

struct css_general_char {
	u64 : 41;
	u32 aif : 1;     /* bit 41 */
+24 −7
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/reboot.h>

#include "../s390mach.h"
#include "css.h"
#include "cio.h"
#include "cio_debug.h"
@@ -530,16 +531,27 @@ EXPORT_SYMBOL_GPL(css_schedule_reprobe);
/*
 * Called from the machine check handler for subchannel report words.
 */
void css_process_crw(int rsid1, int rsid2)
static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
{
	struct subchannel_id mchk_schid;

	CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
		      rsid1, rsid2);
	if (overflow) {
		css_schedule_eval_all();
		return;
	}
	CIO_CRW_EVENT(2, "CRW0 reports slct=%d, oflw=%d, "
		      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
		      crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
		      crw0->erc, crw0->rsid);
	if (crw1)
		CIO_CRW_EVENT(2, "CRW1 reports slct=%d, oflw=%d, "
			      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
			      crw1->slct, crw1->oflw, crw1->chn, crw1->rsc,
			      crw1->anc, crw1->erc, crw1->rsid);
	init_subchannel_id(&mchk_schid);
	mchk_schid.sch_no = rsid1;
	if (rsid2 != 0)
		mchk_schid.ssid = (rsid2 >> 8) & 3;
	mchk_schid.sch_no = crw0->rsid;
	if (crw1)
		mchk_schid.ssid = (crw1->rsid >> 8) & 3;

	/*
	 * Since we are always presented with IPI in the CRW, we have to
@@ -740,6 +752,10 @@ init_channel_subsystem (void)
	if (ret)
		goto out;

	ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw);
	if (ret)
		goto out;

	if ((ret = bus_register(&css_bus_type)))
		goto out;

@@ -817,6 +833,7 @@ init_channel_subsystem (void)
out_bus:
	bus_unregister(&css_bus_type);
out:
	s390_unregister_crw_handler(CRW_RSC_CSS);
	chsc_free_sei_area();
	kfree(slow_subchannel_set);
	printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n",
Loading