static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area) { struct chp_link link; struct chp_id chpid; int status; 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; chp_id_init(&chpid); chpid.id = sei_area->rsid; /* allocate a new channel path structure, if needed */ status = chp_get_status(chpid); if (status < 0) chp_new(chpid); else if (!status) return; memset(&link, 0, sizeof(struct chp_link)); link.chpid = chpid; if ((sei_area->vf & 0xc0) != 0) { link.fla = sei_area->fla; if ((sei_area->vf & 0xc0) == 0xc0) /* full link address */ link.fla_mask = 0xffff; else /* link address */ link.fla_mask = 0xff00; } s390_process_res_acc(&link); }
/* * Function: s390_vary_chpid * Varies the specified chpid online or offline */ static int s390_vary_chpid(struct chp_id chpid, int on) { char dbf_text[15]; int status; sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_text); status = chp_get_status(chpid); if (status < 0) { printk(KERN_ERR "Can't vary unknown chpid %x.%02x\n", chpid.cssid, chpid.id); return -EINVAL; } if (!on && !status) { printk(KERN_ERR "chpid %x.%02x is already offline\n", chpid.cssid, chpid.id); return -EINVAL; } set_chp_logically_online(chpid, on); chsc_chp_vary(chpid, on); return 0; }
/* * Files for the channel path entries. */ static ssize_t chp_status_show(struct device *dev, struct device_attribute *attr, char *buf) { struct channel_path *chp = to_channelpath(dev); if (!chp) return 0; return (chp_get_status(chp->chpid) ? sprintf(buf, "online\n") : sprintf(buf, "offline\n")); }
/** * chp_get_sch_opm - return opm for subchannel * @sch: subchannel * * Calculate and return the operational path mask (opm) based on the chpids * used by the subchannel and the status of the associated channel-paths. */ u8 chp_get_sch_opm(struct subchannel *sch) { struct chp_id chpid; int opm; int i; opm = 0; chp_id_init(&chpid); for (i = 0; i < 8; i++) { opm <<= 1; chpid.id = sch->schib.pmcw.chpid[i]; if (chp_get_status(chpid) != 0) opm |= 1; } return opm; }
void chsc_chp_offline(struct chp_id chpid) { char dbf_txt[15]; struct chp_link link; sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); if (chp_get_status(chpid) <= 0) return; memset(&link, 0, sizeof(struct chp_link)); link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); }
/* * Function: s390_vary_chpid * Varies the specified chpid online or offline */ static int s390_vary_chpid(struct chp_id chpid, int on) { char dbf_text[15]; int status; sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_text); status = chp_get_status(chpid); if (!on && !status) return 0; set_chp_logically_online(chpid, on); chsc_chp_vary(chpid, on); return 0; }
void chsc_chp_online(struct chp_id chpid) { char dbf_txt[15]; struct chp_link link; sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); if (chp_get_status(chpid) != 0) { memset(&link, 0, sizeof(struct chp_link)); link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); for_each_subchannel_staged(__s390_process_res_acc, NULL, &link); } }