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