Commit 184357a5 authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Martin Schwidefsky

[S390] Cleanup of CHSC event handling.

Change CHSC event handling to be more easily extensible.
Signed-off-by: default avatarPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 0f008aa3
...@@ -461,12 +461,7 @@ __get_chpid_from_lir(void *data) ...@@ -461,12 +461,7 @@ __get_chpid_from_lir(void *data)
return (u16) (lir->indesc[0]&0x000000ff); return (u16) (lir->indesc[0]&0x000000ff);
} }
int struct chsc_sei_area {
chsc_process_crw(void)
{
int chpid, ret;
struct res_acc_data res_data;
struct {
struct chsc_header request; struct chsc_header request;
u32 reserved1; u32 reserved1;
u32 reserved2; u32 reserved2;
...@@ -481,124 +476,121 @@ chsc_process_crw(void) ...@@ -481,124 +476,121 @@ chsc_process_crw(void)
u16 rsid; /* reporting source id */ u16 rsid; /* reporting source id */
u32 reserved5; u32 reserved5;
u32 reserved6; u32 reserved6;
u32 ccdf[96]; /* content-code dependent field */ u8 ccdf[4096 - 16 - 24]; /* content-code dependent field */
/* ccdf has to be big enough for a link-incident record */ /* ccdf has to be big enough for a link-incident record */
} __attribute__ ((packed)) *sei_area; } __attribute__ ((packed));
if (!sei_page) static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
return 0; {
/* int chpid;
* build the chsc request block for store event information
* and do the call
* This function is only called by the machine check handler thread,
* so we don't need locking for the sei_page.
*/
sei_area = sei_page;
CIO_TRACE_EVENT( 2, "prcss");
ret = 0;
do {
int ccode, status;
struct device *dev;
memset(sei_area, 0, sizeof(*sei_area));
memset(&res_data, 0, sizeof(struct res_acc_data));
sei_area->request.length = 0x0010;
sei_area->request.code = 0x000e;
ccode = chsc(sei_area);
if (ccode > 0)
return 0;
switch (sei_area->response.code) { CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n",
/* for debug purposes, check for problems */ sei_area->rs, sei_area->rsid);
case 0x0001: if (sei_area->rs != 4)
CIO_CRW_EVENT(4, "chsc_process_crw: event information "
"successfully stored\n");
break; /* everything ok */
case 0x0002:
CIO_CRW_EVENT(2,
"chsc_process_crw: invalid command!\n");
return 0;
case 0x0003:
CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc "
"request block!\n");
return 0; return 0;
case 0x0005:
CIO_CRW_EVENT(2, "chsc_process_crw: no event "
"information stored\n");
return 0;
default:
CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n",
sei_area->response.code);
return 0;
}
/* Check if we might have lost some information. */
if (sei_area->flags & 0x40)
CIO_CRW_EVENT(2, "chsc_process_crw: Event information "
"has been lost due to overflow!\n");
if (sei_area->rs != 4) {
CIO_CRW_EVENT(2, "chsc_process_crw: reporting source "
"(%04X) isn't a chpid!\n",
sei_area->rsid);
continue;
}
/* which kind of information was stored? */
switch (sei_area->cc) {
case 1: /* link incident*/
CIO_CRW_EVENT(4, "chsc_process_crw: "
"channel subsystem reports link incident,"
" reporting source is chpid %x\n",
sei_area->rsid);
chpid = __get_chpid_from_lir(sei_area->ccdf); chpid = __get_chpid_from_lir(sei_area->ccdf);
if (chpid < 0) if (chpid < 0)
CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n", CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n");
__FUNCTION__);
else else
s390_set_chpid_offline(chpid); s390_set_chpid_offline(chpid);
break;
case 2: /* i/o resource accessibiliy */ return 0;
CIO_CRW_EVENT(4, "chsc_process_crw: " }
"channel subsystem reports some I/O "
"devices may have become accessible\n"); static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
pr_debug("Data received after sei: \n"); {
pr_debug("Validity flags: %x\n", sei_area->vf); struct res_acc_data res_data;
struct device *dev;
int status;
int rc;
CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, "
"rs_id=%04x)\n", sei_area->rs, sei_area->rsid);
if (sei_area->rs != 4)
return 0;
/* allocate a new channel path structure, if needed */ /* allocate a new channel path structure, if needed */
status = get_chp_status(sei_area->rsid); status = get_chp_status(sei_area->rsid);
if (status < 0) if (status < 0)
new_channel_path(sei_area->rsid); new_channel_path(sei_area->rsid);
else if (!status) else if (!status)
break; return 0;
dev = get_device(&css[0]->chps[sei_area->rsid]->dev); dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
memset(&res_data, 0, sizeof(struct res_acc_data));
res_data.chp = to_channelpath(dev); res_data.chp = to_channelpath(dev);
pr_debug("chpid: %x", sei_area->rsid);
if ((sei_area->vf & 0xc0) != 0) { if ((sei_area->vf & 0xc0) != 0) {
res_data.fla = sei_area->fla; res_data.fla = sei_area->fla;
if ((sei_area->vf & 0xc0) == 0xc0) { if ((sei_area->vf & 0xc0) == 0xc0)
pr_debug(" full link addr: %x", /* full link address */
sei_area->fla);
res_data.fla_mask = 0xffff; res_data.fla_mask = 0xffff;
} else { else
pr_debug(" link addr: %x", /* link address */
sei_area->fla);
res_data.fla_mask = 0xff00; res_data.fla_mask = 0xff00;
} }
} rc = s390_process_res_acc(&res_data);
ret = s390_process_res_acc(&res_data);
pr_debug("\n\n");
put_device(dev); put_device(dev);
break;
return rc;
}
static int chsc_process_sei(struct chsc_sei_area *sei_area)
{
int rc;
/* Check if we might have lost some information. */
if (sei_area->flags & 0x40)
CIO_CRW_EVENT(2, "chsc: event overflow\n");
/* which kind of information was stored? */
rc = 0;
switch (sei_area->cc) {
case 1: /* link incident*/
rc = chsc_process_sei_link_incident(sei_area);
break;
case 2: /* i/o resource accessibiliy */
rc = chsc_process_sei_res_acc(sei_area);
break;
default: /* other stuff */ default: /* other stuff */
CIO_CRW_EVENT(4, "chsc_process_crw: event %d\n", CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n",
sei_area->cc); sei_area->cc);
break; break;
} }
return rc;
}
int chsc_process_crw(void)
{
struct chsc_sei_area *sei_area;
int ret;
int rc;
if (!sei_page)
return 0;
/* Access to sei_page is serialized through machine check handler
* thread, so no need for locking. */
sei_area = sei_page;
CIO_TRACE_EVENT( 2, "prcss");
ret = 0;
do {
memset(sei_area, 0, sizeof(*sei_area));
sei_area->request.length = 0x0010;
sei_area->request.code = 0x000e;
if (chsc(sei_area))
break;
if (sei_area->response.code == 0x0001) {
CIO_CRW_EVENT(4, "chsc: sei successful\n");
rc = chsc_process_sei(sei_area);
if (rc)
ret = rc;
} else {
CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
sei_area->response.code);
ret = 0;
break;
}
} while (sei_area->flags & 0x80); } while (sei_area->flags & 0x80);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment