/** * chp_process_crw - process channel-path status change * @id: channel-path ID number * @status: non-zero if channel-path has become available, zero otherwise * * Handle channel-report-words indicating that the status of a channel-path * has changed. */ void chp_process_crw(int id, int status) { struct chp_id chpid; chp_id_init(&chpid); chpid.id = id; if (status) { if (!chp_is_registered(chpid)) chp_new(chpid); chsc_chp_online(chpid); } else chsc_chp_offline(chpid); }
/* Perform one configure/deconfigure request. Reschedule work function until * last request. */ static void cfg_func(struct work_struct *work) { struct chp_id chpid; enum cfg_task_t t; int rc; mutex_lock(&cfg_lock); t = cfg_none; chp_id_for_each(&chpid) { t = cfg_get_task(chpid); if (t != cfg_none) { cfg_set_task(chpid, cfg_none); break; } } mutex_unlock(&cfg_lock); switch (t) { case cfg_configure: rc = sclp_chp_configure(chpid); if (rc) CIO_MSG_EVENT(2, "chp: sclp_chp_configure(%x.%02x)=" "%d\n", chpid.cssid, chpid.id, rc); else { info_expire(); chsc_chp_online(chpid); } break; case cfg_deconfigure: rc = sclp_chp_deconfigure(chpid); if (rc) CIO_MSG_EVENT(2, "chp: sclp_chp_deconfigure(%x.%02x)=" "%d\n", chpid.cssid, chpid.id, rc); else { info_expire(); chsc_chp_offline(chpid); } break; case cfg_none: /* Get updated information after last change. */ info_update(); mutex_lock(&cfg_lock); cfg_busy = 0; mutex_unlock(&cfg_lock); wake_up_interruptible(&cfg_wait_queue); return; } queue_work(chp_wq, &cfg_work); }
static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area) { struct chp_id chpid; int id; CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", sei_area->rs, sei_area->rsid); if (sei_area->rs != 4) return; id = __get_chpid_from_lir(sei_area->ccdf); if (id < 0) CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); else { chp_id_init(&chpid); chpid.id = id; chsc_chp_offline(chpid); } }
/** * chp_process_crw - process channel-path status change * @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. */ 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 = crw0->rsid; switch (crw0->erc) { case CRW_ERC_IPARM: /* Path has come. */ if (!chp_is_registered(chpid)) chp_new(chpid); chsc_chp_online(chpid); 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); } }
/* Perform one configure/deconfigure request. Reschedule work function until * last request. */ static void cfg_func(void *data) { struct chp_id chpid; enum cfg_task_t t; mutex_lock(&cfg_lock); t = cfg_none; chp_id_for_each(&chpid) { t = cfg_get_task(chpid); if (t != cfg_none) { cfg_set_task(chpid, cfg_none); break; } } mutex_unlock(&cfg_lock); switch (t) { case cfg_configure: sclp_chp_configure(chpid); info_expire(); chsc_chp_online(chpid); break; case cfg_deconfigure: sclp_chp_deconfigure(chpid); info_expire(); chsc_chp_offline(chpid); break; case cfg_none: /* Get updated information after last change. */ info_update(); mutex_lock(&cfg_lock); cfg_busy = 0; mutex_unlock(&cfg_lock); wake_up_interruptible(&cfg_wait_queue); return; } queue_work(chp_wq, &cfg_work); }