1e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/* 2e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * drivers/s390/cio/chp.c 3e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 4b730f3a933958362ee1080c257f2cc158149310aSebastian Ott * Copyright IBM Corp. 1999,2010 5e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) 6e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Arnd Bergmann (arndb@de.ibm.com) 7e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 8e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 9e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 10e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include <linux/bug.h> 11e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include <linux/workqueue.h> 12e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include <linux/spinlock.h> 133a4c5d5964ed43a5524f6d289fb4cd37d39f3f1aHeiko Carstens#include <linux/export.h> 143a4c5d5964ed43a5524f6d289fb4cd37d39f3f1aHeiko Carstens#include <linux/sched.h> 15e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <linux/init.h> 16e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <linux/jiffies.h> 17e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <linux/wait.h> 18e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <linux/mutex.h> 19a0ea22c3d912de6044f83b07dcc26ee006106139Cornelia Huck#include <linux/errno.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 21e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <asm/chpid.h> 22e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <asm/sclp.h> 23f5daba1d4116d964435ddd99f32b6c80448a496bHeiko Carstens#include <asm/crw.h> 24e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 25e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "cio.h" 26e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "css.h" 27e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "ioasm.h" 28e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "cio_debug.h" 29e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "chp.h" 30e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 31e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#define to_channelpath(device) container_of(device, struct channel_path, dev) 32e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#define CHP_INFO_UPDATE_INTERVAL 1*HZ 33e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 34e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterenum cfg_task_t { 35e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_none, 36e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_configure, 37e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_deconfigure 38e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter}; 39e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 40e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Map for pending configure tasks. */ 41e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic enum cfg_task_t chp_cfg_task[__MAX_CSSID + 1][__MAX_CHPID + 1]; 42e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic DEFINE_MUTEX(cfg_lock); 43e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic int cfg_busy; 44e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 45e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Map for channel-path status. */ 46e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic struct sclp_chp_info chp_info; 47e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic DEFINE_MUTEX(info_lock); 48e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 49e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Time after which channel-path status may be outdated. */ 50e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic unsigned long chp_info_expires; 51e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 52e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Workqueue to perform pending configure tasks. */ 53e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic struct workqueue_struct *chp_wq; 54e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic struct work_struct cfg_work; 55e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 56e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Wait queue for configure completion events. */ 57e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic wait_queue_head_t cfg_wait_queue; 58e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 59e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/* Set vary state for given chpid. */ 60e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic void set_chp_logically_online(struct chp_id chpid, int onoff) 61e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 62e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chpid_to_chp(chpid)->state = onoff; 63e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 64e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 65af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa/* On success return 0 if channel-path is varied offline, 1 if it is varied 66e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * online. Return -ENODEV if channel-path is not registered. */ 67e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterint chp_get_status(struct chp_id chpid) 68e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 69e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return (chpid_to_chp(chpid) ? chpid_to_chp(chpid)->state : -ENODEV); 70e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 71e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 72e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/** 73e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * chp_get_sch_opm - return opm for subchannel 74e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * @sch: subchannel 75e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 76e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Calculate and return the operational path mask (opm) based on the chpids 77e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * used by the subchannel and the status of the associated channel-paths. 78e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 79e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiteru8 chp_get_sch_opm(struct subchannel *sch) 80e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 81e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct chp_id chpid; 82e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int opm; 83e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int i; 84e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 85e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter opm = 0; 86e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp_id_init(&chpid); 87a0ea22c3d912de6044f83b07dcc26ee006106139Cornelia Huck for (i = 0; i < 8; i++) { 88e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter opm <<= 1; 89e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chpid.id = sch->schib.pmcw.chpid[i]; 90e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (chp_get_status(chpid) != 0) 91e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter opm |= 1; 92e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 93e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return opm; 94e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 9544a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia HuckEXPORT_SYMBOL_GPL(chp_get_sch_opm); 96e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 97e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/** 98e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * chp_is_registered - check if a channel-path is registered 99e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * @chpid: channel-path ID 100e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 101e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Return non-zero if a channel-path with the given chpid is registered, 102e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * zero otherwise. 103e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 104e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterint chp_is_registered(struct chp_id chpid) 105e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 106e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return chpid_to_chp(chpid) != NULL; 107e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 108e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 109e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/* 110e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Function: s390_vary_chpid 111e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Varies the specified chpid online or offline 112e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 113e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic int s390_vary_chpid(struct chp_id chpid, int on) 114e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 115e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter char dbf_text[15]; 116e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int status; 117e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 118e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, 119e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chpid.id); 120a0ea22c3d912de6044f83b07dcc26ee006106139Cornelia Huck CIO_TRACE_EVENT(2, dbf_text); 121e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 122e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter status = chp_get_status(chpid); 123c78aa6cbace460081ddc6227f02b6d3203a21585Michael Ernst if (!on && !status) 124c78aa6cbace460081ddc6227f02b6d3203a21585Michael Ernst return 0; 125e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 126e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter set_chp_logically_online(chpid, on); 127e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chsc_chp_vary(chpid, on); 128e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return 0; 129e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 130e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 131e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/* 132e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Channel measurement related functions 133e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 1342c3c8bea608866d8bd9dcf92657d57fdcac011c5Chris Wrightstatic ssize_t chp_measurement_chars_read(struct file *filp, 1352c3c8bea608866d8bd9dcf92657d57fdcac011c5Chris Wright struct kobject *kobj, 13691a6902958f052358899f58683d44e36228d85c2Zhang Rui struct bin_attribute *bin_attr, 13791a6902958f052358899f58683d44e36228d85c2Zhang Rui char *buf, loff_t off, size_t count) 138e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 139e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp; 140364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens struct device *device; 141e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 142364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens device = container_of(kobj, struct device, kobj); 143364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens chp = to_channelpath(device); 144e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp->cmg_chars) 145e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return 0; 146e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 147d9cef21af03eb56473db5bb20d8754f377a498e7Akinobu Mita return memory_read_from_buffer(buf, count, &off, 148d9cef21af03eb56473db5bb20d8754f377a498e7Akinobu Mita chp->cmg_chars, sizeof(struct cmg_chars)); 149e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 150e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 151e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic struct bin_attribute chp_measurement_chars_attr = { 152e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .attr = { 153e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .name = "measurement_chars", 154e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .mode = S_IRUSR, 155e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter }, 156e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .size = sizeof(struct cmg_chars), 157e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .read = chp_measurement_chars_read, 158e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter}; 159e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 160e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic void chp_measurement_copy_block(struct cmg_entry *buf, 161e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_subsystem *css, 162e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct chp_id chpid) 163e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 164e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter void *area; 165e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct cmg_entry *entry, reference_buf; 166e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int idx; 167e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 168e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (chpid.id < 128) { 169e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter area = css->cub_addr1; 170e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter idx = chpid.id; 171e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } else { 172e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter area = css->cub_addr2; 173e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter idx = chpid.id - 128; 174e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 175e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter entry = area + (idx * sizeof(struct cmg_entry)); 176e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter do { 177e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter memcpy(buf, entry, sizeof(*entry)); 178e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter memcpy(&reference_buf, entry, sizeof(*entry)); 179e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } while (reference_buf.values[0] != buf->values[0]); 180e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 181e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 1822c3c8bea608866d8bd9dcf92657d57fdcac011c5Chris Wrightstatic ssize_t chp_measurement_read(struct file *filp, struct kobject *kobj, 18391a6902958f052358899f58683d44e36228d85c2Zhang Rui struct bin_attribute *bin_attr, 18491a6902958f052358899f58683d44e36228d85c2Zhang Rui char *buf, loff_t off, size_t count) 185e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 186e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp; 187e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_subsystem *css; 188364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens struct device *device; 189e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter unsigned int size; 190e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 191364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens device = container_of(kobj, struct device, kobj); 192364c85584e030f7cfc25e9d27ca893dee6f4bf8eHeiko Carstens chp = to_channelpath(device); 193e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter css = to_css(chp->dev.parent); 194e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 195e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter size = sizeof(struct cmg_entry); 196e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 197e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter /* Only allow single reads. */ 198e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (off || count < size) 199e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return 0; 200e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->chpid); 201e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter count = size; 202e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return count; 203e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 204e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 205e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic struct bin_attribute chp_measurement_attr = { 206e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .attr = { 207e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .name = "measurement", 208e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .mode = S_IRUSR, 209e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter }, 210e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .size = sizeof(struct cmg_entry), 211e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .read = chp_measurement_read, 212e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter}; 213e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 214e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleitervoid chp_remove_cmg_attr(struct channel_path *chp) 215e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 216e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); 217e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter device_remove_bin_file(&chp->dev, &chp_measurement_attr); 218e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 219e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 220e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterint chp_add_cmg_attr(struct channel_path *chp) 221e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 222e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int ret; 223e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 224e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = device_create_bin_file(&chp->dev, &chp_measurement_chars_attr); 225e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) 226e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return ret; 227e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = device_create_bin_file(&chp->dev, &chp_measurement_attr); 228e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) 229e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); 230e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return ret; 231e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 232e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 233e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/* 234e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Files for the channel path entries. 235e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 236e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic ssize_t chp_status_show(struct device *dev, 237e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct device_attribute *attr, char *buf) 238e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 239054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck struct channel_path *chp = to_channelpath(dev); 240b730f3a933958362ee1080c257f2cc158149310aSebastian Ott int status; 241e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 242b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_lock(&chp->lock); 243b730f3a933958362ee1080c257f2cc158149310aSebastian Ott status = chp->state; 244b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_unlock(&chp->lock); 245b730f3a933958362ee1080c257f2cc158149310aSebastian Ott 246b730f3a933958362ee1080c257f2cc158149310aSebastian Ott return status ? sprintf(buf, "online\n") : sprintf(buf, "offline\n"); 247e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 248e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 249e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic ssize_t chp_status_write(struct device *dev, 250e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct device_attribute *attr, 251e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter const char *buf, size_t count) 252e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 253054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck struct channel_path *cp = to_channelpath(dev); 254e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter char cmd[10]; 255e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int num_args; 256e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int error; 257e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 258e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter num_args = sscanf(buf, "%5s", cmd); 259e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!num_args) 260e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return count; 261e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 262b730f3a933958362ee1080c257f2cc158149310aSebastian Ott if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) { 263b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_lock(&cp->lock); 264e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter error = s390_vary_chpid(cp->chpid, 1); 265b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_unlock(&cp->lock); 266b730f3a933958362ee1080c257f2cc158149310aSebastian Ott } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) { 267b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_lock(&cp->lock); 268e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter error = s390_vary_chpid(cp->chpid, 0); 269b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_unlock(&cp->lock); 270b730f3a933958362ee1080c257f2cc158149310aSebastian Ott } else 271e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter error = -EINVAL; 272e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 273e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return error < 0 ? error : count; 274e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 275e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 276e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write); 277e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 278e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic ssize_t chp_configure_show(struct device *dev, 279e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct device_attribute *attr, char *buf) 280e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 281e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct channel_path *cp; 282e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter int status; 283e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 284054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck cp = to_channelpath(dev); 285e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter status = chp_info_get_status(cp->chpid); 286e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (status < 0) 287e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return status; 288e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 289e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return snprintf(buf, PAGE_SIZE, "%d\n", status); 290e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 291e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 292e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic int cfg_wait_idle(void); 293e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 294e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic ssize_t chp_configure_write(struct device *dev, 295e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct device_attribute *attr, 296e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter const char *buf, size_t count) 297e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 298e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct channel_path *cp; 299e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter int val; 300e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter char delim; 301e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 302e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (sscanf(buf, "%d %c", &val, &delim) != 1) 303e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return -EINVAL; 304e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (val != 0 && val != 1) 305e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return -EINVAL; 306054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck cp = to_channelpath(dev); 307e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_cfg_schedule(cp->chpid, val); 308e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_wait_idle(); 309e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 310e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return count; 311e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 312e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 313e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic DEVICE_ATTR(configure, 0644, chp_configure_show, chp_configure_write); 314e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 315e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic ssize_t chp_type_show(struct device *dev, struct device_attribute *attr, 316e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter char *buf) 317e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 318054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck struct channel_path *chp = to_channelpath(dev); 319b730f3a933958362ee1080c257f2cc158149310aSebastian Ott u8 type; 320e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 321b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_lock(&chp->lock); 322b730f3a933958362ee1080c257f2cc158149310aSebastian Ott type = chp->desc.desc; 323b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_unlock(&chp->lock); 324b730f3a933958362ee1080c257f2cc158149310aSebastian Ott return sprintf(buf, "%x\n", type); 325e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 326e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 327e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic DEVICE_ATTR(type, 0444, chp_type_show, NULL); 328e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 329e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic ssize_t chp_cmg_show(struct device *dev, struct device_attribute *attr, 330e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter char *buf) 331e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 332e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp = to_channelpath(dev); 333e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 334e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp) 335e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return 0; 336e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (chp->cmg == -1) /* channel measurements not available */ 337e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return sprintf(buf, "unknown\n"); 338e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return sprintf(buf, "%x\n", chp->cmg); 339e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 340e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 341e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL); 342e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 343e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic ssize_t chp_shared_show(struct device *dev, 344e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct device_attribute *attr, char *buf) 345e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 346e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp = to_channelpath(dev); 347e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 348e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp) 349e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return 0; 350e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (chp->shared == -1) /* channel measurements not available */ 351e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return sprintf(buf, "unknown\n"); 352e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return sprintf(buf, "%x\n", chp->shared); 353e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 354e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 355e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); 356e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 357a0ea22c3d912de6044f83b07dcc26ee006106139Cornelia Huckstatic struct attribute *chp_attrs[] = { 358e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter &dev_attr_status.attr, 359e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter &dev_attr_configure.attr, 360e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter &dev_attr_type.attr, 361e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter &dev_attr_cmg.attr, 362e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter &dev_attr_shared.attr, 363e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter NULL, 364e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter}; 365e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 366e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic struct attribute_group chp_attr_group = { 367e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter .attrs = chp_attrs, 368e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter}; 369e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 370e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterstatic void chp_release(struct device *dev) 371e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 372e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *cp; 373e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 374054696077a6c4f9e306321d45b5762d6ea7940e1Cornelia Huck cp = to_channelpath(dev); 375e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter kfree(cp); 376e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 377e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 378e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/** 379e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * chp_new - register a new channel-path 380e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * @chpid - channel-path ID 381e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 382e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Create and register data structure representing new channel-path. Return 383e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * zero on success, non-zero otherwise. 384e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 385e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterint chp_new(struct chp_id chpid) 386e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 387e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp; 388e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter int ret; 389e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 390e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (chp_is_registered(chpid)) 391e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return 0; 392e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp = kzalloc(sizeof(struct channel_path), GFP_KERNEL); 393e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp) 394e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return -ENOMEM; 395e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 396e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter /* fill in status, etc. */ 397e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp->chpid = chpid; 398e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp->state = 1; 3997c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck chp->dev.parent = &channel_subsystems[chpid.cssid]->device; 400e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp->dev.release = chp_release; 401b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_init(&chp->lock); 402e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 403e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter /* Obtain channel path description and fill it in. */ 4049d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc); 405e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) 406e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter goto out_free; 407c9182e0f42c5646e670c2166b6d6638052d574afPeter Oberparleiter if ((chp->desc.flags & 0x80) == 0) { 408c9182e0f42c5646e670c2166b6d6638052d574afPeter Oberparleiter ret = -ENODEV; 409c9182e0f42c5646e670c2166b6d6638052d574afPeter Oberparleiter goto out_free; 410c9182e0f42c5646e670c2166b6d6638052d574afPeter Oberparleiter } 411e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter /* Get channel-measurement characteristics. */ 41275784c00876c88ca6e955c39cbb5d47cf408fd3cCornelia Huck if (css_chsc_characteristics.scmc && css_chsc_characteristics.secm) { 413e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = chsc_get_channel_measurement_chars(chp); 414e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) 415e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter goto out_free; 416e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } else { 417e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp->cmg = -1; 418e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 419ec00440786f413133997396308f41184eb705a6dMichael Ernst dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id); 420e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 421e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter /* make it known to the system */ 422e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = device_register(&chp->dev); 423e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) { 424e556bbbd9d2ff2b158915945ac82e2ac7def4d2fCornelia Huck CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n", 425e556bbbd9d2ff2b158915945ac82e2ac7def4d2fCornelia Huck chpid.cssid, chpid.id, ret); 426c6304933274f8e3cc6983d496456757ac8ab2e0bSebastian Ott put_device(&chp->dev); 427c6304933274f8e3cc6983d496456757ac8ab2e0bSebastian Ott goto out; 428e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 429e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); 430e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) { 431e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter device_unregister(&chp->dev); 432a2164b8174f13b7315c3f45c0b48dec619285096Cornelia Huck goto out; 433e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 4347c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck mutex_lock(&channel_subsystems[chpid.cssid]->mutex); 4357c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck if (channel_subsystems[chpid.cssid]->cm_enabled) { 436e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter ret = chp_add_cmg_attr(chp); 437e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (ret) { 438e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); 439e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter device_unregister(&chp->dev); 4407c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); 441a2164b8174f13b7315c3f45c0b48dec619285096Cornelia Huck goto out; 442e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 443e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter } 4447c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; 4457c9f4e3aaae020fc674f52393cbac1bdb648bf90Cornelia Huck mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); 446a2164b8174f13b7315c3f45c0b48dec619285096Cornelia Huck goto out; 447e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiterout_free: 448e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter kfree(chp); 449a2164b8174f13b7315c3f45c0b48dec619285096Cornelia Huckout: 450e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return ret; 451e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 452e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 453e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/** 454e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * chp_get_chp_desc - return newly allocated channel-path description 455e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * @chpid: channel-path ID 456e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 457e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * On success return a newly allocated copy of the channel-path description 458e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * data associated with the given channel-path ID. Return %NULL on error. 459e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 460e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleitervoid *chp_get_chp_desc(struct chp_id chpid) 461e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 462e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path *chp; 463e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct channel_path_desc *desc; 464e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 465e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp = chpid_to_chp(chpid); 466e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp) 467e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return NULL; 468e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); 469e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!desc) 470e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return NULL; 471b730f3a933958362ee1080c257f2cc158149310aSebastian Ott 472b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_lock(&chp->lock); 473e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter memcpy(desc, &chp->desc, sizeof(struct channel_path_desc)); 474b730f3a933958362ee1080c257f2cc158149310aSebastian Ott mutex_unlock(&chp->lock); 475e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter return desc; 476e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 477e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 478e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter/** 479e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * chp_process_crw - process channel-path status change 480c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * @crw0: channel report-word to handler 481c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * @crw1: second channel-report word (always NULL) 482c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * @overflow: crw overflow indication 483e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * 484e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * Handle channel-report-words indicating that the status of a channel-path 485e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter * has changed. 486e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter */ 487c11561897ab57a3c11e0a284ba17795d580589abCornelia Huckstatic void chp_process_crw(struct crw *crw0, struct crw *crw1, 488c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck int overflow) 489e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter{ 490e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter struct chp_id chpid; 491e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter 492c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck if (overflow) { 493c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck css_schedule_eval_all(); 494c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck return; 495c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck } 496c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, " 497c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 498c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc, 499c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck crw0->erc, crw0->rsid); 500c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck /* 501c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * Check for solicited machine checks. These are 502c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * created by reset channel path and need not be 503c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck * handled here. 504c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck */ 505c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck if (crw0->slct) { 506c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck CIO_CRW_EVENT(2, "solicited machine check for " 507c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck "channel path %02X\n", crw0->rsid); 508c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck return; 509c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck } 510e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp_id_init(&chpid); 511c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck chpid.id = crw0->rsid; 512c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck switch (crw0->erc) { 513c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck case CRW_ERC_IPARM: /* Path has come. */ 514e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter if (!chp_is_registered(chpid)) 515e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chp_new(chpid); 51683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter chsc_chp_online(chpid); 517c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck break; 518c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck case CRW_ERC_PERRI: /* Path has gone. */ 519c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck case CRW_ERC_PERRN: 520e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter chsc_chp_offline(chpid); 521c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck break; 522c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck default: 523c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck CIO_CRW_EVENT(2, "Don't know how to handle erc=%x\n", 524c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck crw0->erc); 525c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck } 526e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter} 527e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 52899611f87176b2a908d8c66ab19a5fc550a3cd13aCornelia Huckint chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct chp_link *link) 529c820de39bd083222f5be2563181c87493e436f7cCornelia Huck{ 530c820de39bd083222f5be2563181c87493e436f7cCornelia Huck int i; 531c820de39bd083222f5be2563181c87493e436f7cCornelia Huck int mask; 532c820de39bd083222f5be2563181c87493e436f7cCornelia Huck 533c820de39bd083222f5be2563181c87493e436f7cCornelia Huck for (i = 0; i < 8; i++) { 534c820de39bd083222f5be2563181c87493e436f7cCornelia Huck mask = 0x80 >> i; 535c820de39bd083222f5be2563181c87493e436f7cCornelia Huck if (!(ssd->path_mask & mask)) 536c820de39bd083222f5be2563181c87493e436f7cCornelia Huck continue; 53799611f87176b2a908d8c66ab19a5fc550a3cd13aCornelia Huck if (!chp_id_is_equal(&ssd->chpid[i], &link->chpid)) 538c820de39bd083222f5be2563181c87493e436f7cCornelia Huck continue; 539c820de39bd083222f5be2563181c87493e436f7cCornelia Huck if ((ssd->fla_valid_mask & mask) && 54099611f87176b2a908d8c66ab19a5fc550a3cd13aCornelia Huck ((ssd->fla[i] & link->fla_mask) != link->fla)) 541c820de39bd083222f5be2563181c87493e436f7cCornelia Huck continue; 542c820de39bd083222f5be2563181c87493e436f7cCornelia Huck return mask; 543c820de39bd083222f5be2563181c87493e436f7cCornelia Huck } 544c820de39bd083222f5be2563181c87493e436f7cCornelia Huck return 0; 545c820de39bd083222f5be2563181c87493e436f7cCornelia Huck} 546c820de39bd083222f5be2563181c87493e436f7cCornelia HuckEXPORT_SYMBOL_GPL(chp_ssd_get_mask); 547c820de39bd083222f5be2563181c87493e436f7cCornelia Huck 548e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic inline int info_bit_num(struct chp_id id) 549e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 550e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return id.id + id.cssid * (__MAX_CHPID + 1); 551e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 552e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 553e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Force chp_info refresh on next call to info_validate(). */ 554e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic void info_expire(void) 555e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 556e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&info_lock); 557e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_info_expires = jiffies - 1; 558e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&info_lock); 559e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 560e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 561e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Ensure that chp_info is up-to-date. */ 562e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic int info_update(void) 563e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 564e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter int rc; 565e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 566e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&info_lock); 567e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = 0; 568e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (time_after(jiffies, chp_info_expires)) { 569e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter /* Data is too old, update. */ 570e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = sclp_chp_read_info(&chp_info); 571e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_info_expires = jiffies + CHP_INFO_UPDATE_INTERVAL ; 572e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter } 573e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&info_lock); 574e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 575e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return rc; 576e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 577e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 578e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/** 579e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * chp_info_get_status - retrieve configure status of a channel-path 580e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * @chpid: channel-path ID 581e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * 582e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * On success, return 0 for standby, 1 for configured, 2 for reserved, 583e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * 3 for not recognized. Return negative error code on error. 584e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter */ 585e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterint chp_info_get_status(struct chp_id chpid) 586e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 587e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter int rc; 588e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter int bit; 589e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 590e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = info_update(); 591e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (rc) 592e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return rc; 593e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 594e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter bit = info_bit_num(chpid); 595e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&info_lock); 596e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (!chp_test_bit(chp_info.recognized, bit)) 597e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = CHP_STATUS_NOT_RECOGNIZED; 598e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter else if (chp_test_bit(chp_info.configured, bit)) 599e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = CHP_STATUS_CONFIGURED; 600e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter else if (chp_test_bit(chp_info.standby, bit)) 601e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = CHP_STATUS_STANDBY; 602e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter else 603e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter rc = CHP_STATUS_RESERVED; 604e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&info_lock); 605e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 606e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return rc; 607e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 608e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 609e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Return configure task for chpid. */ 610e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic enum cfg_task_t cfg_get_task(struct chp_id chpid) 611e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 612e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return chp_cfg_task[chpid.cssid][chpid.id]; 613e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 614e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 615e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Set configure task for chpid. */ 616e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic void cfg_set_task(struct chp_id chpid, enum cfg_task_t cfg) 617e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 618e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_cfg_task[chpid.cssid][chpid.id] = cfg; 619e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 620e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 621e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/* Perform one configure/deconfigure request. Reschedule work function until 622e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * last request. */ 623e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic void cfg_func(struct work_struct *work) 624e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 625e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct chp_id chpid; 626e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter enum cfg_task_t t; 627683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter int rc; 628e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 629e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&cfg_lock); 630e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter t = cfg_none; 631e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_id_for_each(&chpid) { 632e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter t = cfg_get_task(chpid); 633e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (t != cfg_none) { 634e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_set_task(chpid, cfg_none); 635e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter break; 636e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter } 637e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter } 638e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&cfg_lock); 639e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 640e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter switch (t) { 641e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter case cfg_configure: 642683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter rc = sclp_chp_configure(chpid); 643683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter if (rc) 644683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter CIO_MSG_EVENT(2, "chp: sclp_chp_configure(%x.%02x)=" 645683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter "%d\n", chpid.cssid, chpid.id, rc); 646683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter else { 647683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter info_expire(); 648683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter chsc_chp_online(chpid); 649683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter } 650e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter break; 651e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter case cfg_deconfigure: 652683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter rc = sclp_chp_deconfigure(chpid); 653683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter if (rc) 654683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter CIO_MSG_EVENT(2, "chp: sclp_chp_deconfigure(%x.%02x)=" 655683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter "%d\n", chpid.cssid, chpid.id, rc); 656683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter else { 657683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter info_expire(); 658683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter chsc_chp_offline(chpid); 659683c5418e6ac9f40f925dab6f547a5b0a4ad43c6Peter Oberparleiter } 660e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter break; 661e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter case cfg_none: 662e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter /* Get updated information after last change. */ 663e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter info_update(); 664e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&cfg_lock); 665e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_busy = 0; 666e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&cfg_lock); 667e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter wake_up_interruptible(&cfg_wait_queue); 668e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return; 669e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter } 670e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter queue_work(chp_wq, &cfg_work); 671e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 672e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 673e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/** 674e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * chp_cfg_schedule - schedule chpid configuration request 675e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * @chpid - channel-path ID 676e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * @configure - Non-zero for configure, zero for deconfigure 677e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * 678e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * Schedule a channel-path configuration/deconfiguration request. 679e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter */ 680e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleitervoid chp_cfg_schedule(struct chp_id chpid, int configure) 681e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 682e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter CIO_MSG_EVENT(2, "chp_cfg_sched%x.%02x=%d\n", chpid.cssid, chpid.id, 683e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter configure); 684e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&cfg_lock); 685e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_set_task(chpid, configure ? cfg_configure : cfg_deconfigure); 686e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_busy = 1; 687e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&cfg_lock); 688e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter queue_work(chp_wq, &cfg_work); 689e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 690e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 691e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter/** 692e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * chp_cfg_cancel_deconfigure - cancel chpid deconfiguration request 693e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * @chpid - channel-path ID 694e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * 695e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * Cancel an active channel-path deconfiguration request if it has not yet 696e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter * been performed. 697e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter */ 698e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleitervoid chp_cfg_cancel_deconfigure(struct chp_id chpid) 699e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 700e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter CIO_MSG_EVENT(2, "chp_cfg_cancel:%x.%02x\n", chpid.cssid, chpid.id); 701e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_lock(&cfg_lock); 702e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (cfg_get_task(chpid) == cfg_deconfigure) 703e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter cfg_set_task(chpid, cfg_none); 704e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter mutex_unlock(&cfg_lock); 705e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 706e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 707e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic int cfg_wait_idle(void) 708e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 709e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (wait_event_interruptible(cfg_wait_queue, !cfg_busy)) 710e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return -ERESTARTSYS; 711e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return 0; 712e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 713e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 714e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiterstatic int __init chp_init(void) 715e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter{ 716e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter struct chp_id chpid; 717c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck int ret; 718e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 719f5daba1d4116d964435ddd99f32b6c80448a496bHeiko Carstens ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw); 720c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck if (ret) 721c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck return ret; 722e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_wq = create_singlethread_workqueue("cio_chp"); 723c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck if (!chp_wq) { 724f5daba1d4116d964435ddd99f32b6c80448a496bHeiko Carstens crw_unregister_handler(CRW_RSC_CPATH); 725e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return -ENOMEM; 726c11561897ab57a3c11e0a284ba17795d580589abCornelia Huck } 727e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter INIT_WORK(&cfg_work, cfg_func); 728e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter init_waitqueue_head(&cfg_wait_queue); 729e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (info_update()) 730e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return 0; 731e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter /* Register available channel-paths. */ 732e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_id_for_each(&chpid) { 733e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter if (chp_info_get_status(chpid) != CHP_STATUS_NOT_RECOGNIZED) 734e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter chp_new(chpid); 735e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter } 736e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 737e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter return 0; 738e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter} 739e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter 740e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleitersubsys_initcall(chp_init); 741