1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Driver for s390 eadm subchannels
4 *
5 * Copyright IBM Corp. 2012
6 * Author(s): Sebastian Ott <sebott@linux.vnet.ibm.com>
7 */
8
9#include <linux/kernel_stat.h>
10#include <linux/completion.h>
11#include <linux/workqueue.h>
12#include <linux/spinlock.h>
13#include <linux/device.h>
14#include <linux/module.h>
15#include <linux/timer.h>
16#include <linux/slab.h>
17#include <linux/list.h>
18
19#include <asm/css_chars.h>
20#include <asm/debug.h>
21#include <asm/isc.h>
22#include <asm/cio.h>
23#include <asm/scsw.h>
24#include <asm/eadm.h>
25
26#include "eadm_sch.h"
27#include "ioasm.h"
28#include "cio.h"
29#include "css.h"
30#include "orb.h"
31
32MODULE_DESCRIPTION("driver for s390 eadm subchannels");
33MODULE_LICENSE("GPL");
34
35#define EADM_TIMEOUT (7 * HZ)
36static DEFINE_SPINLOCK(list_lock);
37static LIST_HEAD(eadm_list);
38
39static debug_info_t *eadm_debug;
40
41#define EADM_LOG(imp, txt) do {					\
42		debug_text_event(eadm_debug, imp, txt);		\
43	} while (0)
44
45static void EADM_LOG_HEX(int level, void *data, int length)
46{
47	debug_event(eadm_debug, level, data, length);
48}
49
50static void orb_init(union orb *orb)
51{
52	memset(orb, 0, sizeof(union orb));
53	orb->eadm.compat1 = 1;
54	orb->eadm.compat2 = 1;
55	orb->eadm.fmt = 1;
56	orb->eadm.x = 1;
57}
58
59static int eadm_subchannel_start(struct subchannel *sch, struct aob *aob)
60{
61	union orb *orb = &get_eadm_private(sch)->orb;
62	int cc;
63
64	orb_init(orb);
65	orb->eadm.aob = (u32)__pa(aob);
66	orb->eadm.intparm = (u32)(addr_t)sch;
67	orb->eadm.key = PAGE_DEFAULT_KEY >> 4;
68
69	EADM_LOG(6, "start");
70	EADM_LOG_HEX(6, &sch->schid, sizeof(sch->schid));
71
72	cc = ssch(sch->schid, orb);
73	switch (cc) {
74	case 0:
75		sch->schib.scsw.eadm.actl |= SCSW_ACTL_START_PEND;
76		break;
77	case 1:		/* status pending */
78	case 2:		/* busy */
79		return -EBUSY;
80	case 3:		/* not operational */
81		return -ENODEV;
82	}
83	return 0;
84}
85
86static int eadm_subchannel_clear(struct subchannel *sch)
87{
88	int cc;
89
90	cc = csch(sch->schid);
91	if (cc)
92		return -ENODEV;
93
94	sch->schib.scsw.eadm.actl |= SCSW_ACTL_CLEAR_PEND;
95	return 0;
96}
97
98static void eadm_subchannel_timeout(struct timer_list *t)
99{
100	struct eadm_private *private = from_timer(private, t, timer);
101	struct subchannel *sch = private->sch;
102
103	spin_lock_irq(sch->lock);
104	EADM_LOG(1, "timeout");
105	EADM_LOG_HEX(1, &sch->schid, sizeof(sch->schid));
106	if (eadm_subchannel_clear(sch))
107		EADM_LOG(0, "clear failed");
108	spin_unlock_irq(sch->lock);
109}
110
111static void eadm_subchannel_set_timeout(struct subchannel *sch, int expires)
112{
113	struct eadm_private *private = get_eadm_private(sch);
114
115	if (expires == 0) {
116		del_timer(&private->timer);
117		return;
118	}
119	if (timer_pending(&private->timer)) {
120		if (mod_timer(&private->timer, jiffies + expires))
121			return;
122	}
123	private->timer.expires = jiffies + expires;
124	add_timer(&private->timer);
125}
126
127static void eadm_subchannel_irq(struct subchannel *sch)
128{
129	struct eadm_private *private = get_eadm_private(sch);
130	struct eadm_scsw *scsw = &sch->schib.scsw.eadm;
131	struct irb *irb = this_cpu_ptr(&cio_irb);
132	blk_status_t error = BLK_STS_OK;
133
134	EADM_LOG(6, "irq");
135	EADM_LOG_HEX(6, irb, sizeof(*irb));
136
137	inc_irq_stat(IRQIO_ADM);
138
139	if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))
140	    && scsw->eswf == 1 && irb->esw.eadm.erw.r)
141		error = BLK_STS_IOERR;
142
143	if (scsw->fctl & SCSW_FCTL_CLEAR_FUNC)
144		error = BLK_STS_TIMEOUT;
145
146	eadm_subchannel_set_timeout(sch, 0);
147
148	if (private->state != EADM_BUSY) {
149		EADM_LOG(1, "irq unsol");
150		EADM_LOG_HEX(1, irb, sizeof(*irb));
151		private->state = EADM_NOT_OPER;
152		css_sched_sch_todo(sch, SCH_TODO_EVAL);
153		return;
154	}
155	scm_irq_handler((struct aob *)(unsigned long)scsw->aob, error);
156	private->state = EADM_IDLE;
157
158	if (private->completion)
159		complete(private->completion);
160}
161
162static struct subchannel *eadm_get_idle_sch(void)
163{
164	struct eadm_private *private;
165	struct subchannel *sch;
166	unsigned long flags;
167
168	spin_lock_irqsave(&list_lock, flags);
169	list_for_each_entry(private, &eadm_list, head) {
170		sch = private->sch;
171		spin_lock(sch->lock);
172		if (private->state == EADM_IDLE) {
173			private->state = EADM_BUSY;
174			list_move_tail(&private->head, &eadm_list);
175			spin_unlock(sch->lock);
176			spin_unlock_irqrestore(&list_lock, flags);
177
178			return sch;
179		}
180		spin_unlock(sch->lock);
181	}
182	spin_unlock_irqrestore(&list_lock, flags);
183
184	return NULL;
185}
186
187int eadm_start_aob(struct aob *aob)
188{
189	struct eadm_private *private;
190	struct subchannel *sch;
191	unsigned long flags;
192	int ret;
193
194	sch = eadm_get_idle_sch();
195	if (!sch)
196		return -EBUSY;
197
198	spin_lock_irqsave(sch->lock, flags);
199	eadm_subchannel_set_timeout(sch, EADM_TIMEOUT);
200	ret = eadm_subchannel_start(sch, aob);
201	if (!ret)
202		goto out_unlock;
203
204	/* Handle start subchannel failure. */
205	eadm_subchannel_set_timeout(sch, 0);
206	private = get_eadm_private(sch);
207	private->state = EADM_NOT_OPER;
208	css_sched_sch_todo(sch, SCH_TODO_EVAL);
209
210out_unlock:
211	spin_unlock_irqrestore(sch->lock, flags);
212
213	return ret;
214}
215EXPORT_SYMBOL_GPL(eadm_start_aob);
216
217static int eadm_subchannel_probe(struct subchannel *sch)
218{
219	struct eadm_private *private;
220	int ret;
221
222	private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
223	if (!private)
224		return -ENOMEM;
225
226	INIT_LIST_HEAD(&private->head);
227	timer_setup(&private->timer, eadm_subchannel_timeout, 0);
228
229	spin_lock_irq(sch->lock);
230	set_eadm_private(sch, private);
231	private->state = EADM_IDLE;
232	private->sch = sch;
233	sch->isc = EADM_SCH_ISC;
234	ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
235	if (ret) {
236		set_eadm_private(sch, NULL);
237		spin_unlock_irq(sch->lock);
238		kfree(private);
239		goto out;
240	}
241	spin_unlock_irq(sch->lock);
242
243	spin_lock_irq(&list_lock);
244	list_add(&private->head, &eadm_list);
245	spin_unlock_irq(&list_lock);
246
247	if (dev_get_uevent_suppress(&sch->dev)) {
248		dev_set_uevent_suppress(&sch->dev, 0);
249		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
250	}
251out:
252	return ret;
253}
254
255static void eadm_quiesce(struct subchannel *sch)
256{
257	struct eadm_private *private = get_eadm_private(sch);
258	DECLARE_COMPLETION_ONSTACK(completion);
259	int ret;
260
261	spin_lock_irq(sch->lock);
262	if (private->state != EADM_BUSY)
263		goto disable;
264
265	if (eadm_subchannel_clear(sch))
266		goto disable;
267
268	private->completion = &completion;
269	spin_unlock_irq(sch->lock);
270
271	wait_for_completion_io(&completion);
272
273	spin_lock_irq(sch->lock);
274	private->completion = NULL;
275
276disable:
277	eadm_subchannel_set_timeout(sch, 0);
278	do {
279		ret = cio_disable_subchannel(sch);
280	} while (ret == -EBUSY);
281
282	spin_unlock_irq(sch->lock);
283}
284
285static int eadm_subchannel_remove(struct subchannel *sch)
286{
287	struct eadm_private *private = get_eadm_private(sch);
288
289	spin_lock_irq(&list_lock);
290	list_del(&private->head);
291	spin_unlock_irq(&list_lock);
292
293	eadm_quiesce(sch);
294
295	spin_lock_irq(sch->lock);
296	set_eadm_private(sch, NULL);
297	spin_unlock_irq(sch->lock);
298
299	kfree(private);
300
301	return 0;
302}
303
304static void eadm_subchannel_shutdown(struct subchannel *sch)
305{
306	eadm_quiesce(sch);
307}
308
309static int eadm_subchannel_freeze(struct subchannel *sch)
310{
311	return cio_disable_subchannel(sch);
312}
313
314static int eadm_subchannel_restore(struct subchannel *sch)
315{
316	return cio_enable_subchannel(sch, (u32)(unsigned long)sch);
317}
318
319/**
320 * eadm_subchannel_sch_event - process subchannel event
321 * @sch: subchannel
322 * @process: non-zero if function is called in process context
323 *
324 * An unspecified event occurred for this subchannel. Adjust data according
325 * to the current operational state of the subchannel. Return zero when the
326 * event has been handled sufficiently or -EAGAIN when this function should
327 * be called again in process context.
328 */
329static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
330{
331	struct eadm_private *private;
332	unsigned long flags;
333
334	spin_lock_irqsave(sch->lock, flags);
335	if (!device_is_registered(&sch->dev))
336		goto out_unlock;
337
338	if (work_pending(&sch->todo_work))
339		goto out_unlock;
340
341	if (cio_update_schib(sch)) {
342		css_sched_sch_todo(sch, SCH_TODO_UNREG);
343		goto out_unlock;
344	}
345	private = get_eadm_private(sch);
346	if (private->state == EADM_NOT_OPER)
347		private->state = EADM_IDLE;
348
349out_unlock:
350	spin_unlock_irqrestore(sch->lock, flags);
351
352	return 0;
353}
354
355static struct css_device_id eadm_subchannel_ids[] = {
356	{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_ADM, },
357	{ /* end of list */ },
358};
359MODULE_DEVICE_TABLE(css, eadm_subchannel_ids);
360
361static struct css_driver eadm_subchannel_driver = {
362	.drv = {
363		.name = "eadm_subchannel",
364		.owner = THIS_MODULE,
365	},
366	.subchannel_type = eadm_subchannel_ids,
367	.irq = eadm_subchannel_irq,
368	.probe = eadm_subchannel_probe,
369	.remove = eadm_subchannel_remove,
370	.shutdown = eadm_subchannel_shutdown,
371	.sch_event = eadm_subchannel_sch_event,
372	.freeze = eadm_subchannel_freeze,
373	.thaw = eadm_subchannel_restore,
374	.restore = eadm_subchannel_restore,
375};
376
377static int __init eadm_sch_init(void)
378{
379	int ret;
380
381	if (!css_general_characteristics.eadm)
382		return -ENXIO;
383
384	eadm_debug = debug_register("eadm_log", 16, 1, 16);
385	if (!eadm_debug)
386		return -ENOMEM;
387
388	debug_register_view(eadm_debug, &debug_hex_ascii_view);
389	debug_set_level(eadm_debug, 2);
390
391	isc_register(EADM_SCH_ISC);
392	ret = css_driver_register(&eadm_subchannel_driver);
393	if (ret)
394		goto cleanup;
395
396	return ret;
397
398cleanup:
399	isc_unregister(EADM_SCH_ISC);
400	debug_unregister(eadm_debug);
401	return ret;
402}
403
404static void __exit eadm_sch_exit(void)
405{
406	css_driver_unregister(&eadm_subchannel_driver);
407	isc_unregister(EADM_SCH_ISC);
408	debug_unregister(eadm_debug);
409}
410module_init(eadm_sch_init);
411module_exit(eadm_sch_exit);
412