1
2
3
4
5
6
7
8
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/errno.h>
12#include <linux/slab.h>
13#include <linux/list.h>
14#include <linux/device.h>
15#include <linux/delay.h>
16
17#include <asm/ccwdev.h>
18#include <asm/idals.h>
19#include <asm/chpid.h>
20
21#include "cio.h"
22#include "cio_debug.h"
23#include "css.h"
24#include "chsc.h"
25#include "device.h"
26#include "chp.h"
27
28
29
30
31
32
33
34
35
36
37
38int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
39{
40
41
42
43 if ((flags & CCWDEV_EARLY_NOTIFICATION) &&
44 (flags & CCWDEV_REPORT_ALL))
45 return -EINVAL;
46 cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
47 cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
48 cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
49 cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
50 return 0;
51}
52
53
54
55
56
57
58
59
60
61
62int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
63{
64
65
66
67 if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
68 (flags & CCWDEV_REPORT_ALL)) ||
69 ((flags & CCWDEV_EARLY_NOTIFICATION) &&
70 cdev->private->options.repall) ||
71 ((flags & CCWDEV_REPORT_ALL) &&
72 cdev->private->options.fast))
73 return -EINVAL;
74 cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
75 cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
76 cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
77 cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
78 return 0;
79}
80
81
82
83
84
85
86
87
88void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
89{
90 cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
91 cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
92 cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
93 cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
94}
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
112{
113 struct subchannel *sch;
114 int ret;
115
116 if (!cdev)
117 return -ENODEV;
118 if (cdev->private->state == DEV_STATE_NOT_OPER)
119 return -ENODEV;
120 if (cdev->private->state != DEV_STATE_ONLINE &&
121 cdev->private->state != DEV_STATE_W4SENSE)
122 return -EINVAL;
123 sch = to_subchannel(cdev->dev.parent);
124 if (!sch)
125 return -ENODEV;
126 ret = cio_clear(sch);
127 if (ret == 0)
128 cdev->private->intparm = intparm;
129 return ret;
130}
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
157 unsigned long intparm, __u8 lpm, __u8 key,
158 unsigned long flags)
159{
160 struct subchannel *sch;
161 int ret;
162
163 if (!cdev)
164 return -ENODEV;
165 sch = to_subchannel(cdev->dev.parent);
166 if (!sch)
167 return -ENODEV;
168 if (cdev->private->state == DEV_STATE_NOT_OPER)
169 return -ENODEV;
170 if (cdev->private->state == DEV_STATE_VERIFY ||
171 cdev->private->state == DEV_STATE_CLEAR_VERIFY) {
172
173 if (!cdev->private->flags.fake_irb) {
174 cdev->private->flags.fake_irb = 1;
175 cdev->private->intparm = intparm;
176 return 0;
177 } else
178
179 return -EBUSY;
180 }
181 if (cdev->private->state != DEV_STATE_ONLINE ||
182 ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
183 !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
184 cdev->private->flags.doverify)
185 return -EBUSY;
186 ret = cio_set_options (sch, flags);
187 if (ret)
188 return ret;
189
190 if (lpm) {
191 lpm &= sch->opm;
192 if (lpm == 0)
193 return -EACCES;
194 }
195 ret = cio_start_key (sch, cpa, lpm, key);
196 if (ret == 0)
197 cdev->private->intparm = intparm;
198 return ret;
199}
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
231 unsigned long intparm, __u8 lpm, __u8 key,
232 unsigned long flags, int expires)
233{
234 int ret;
235
236 if (!cdev)
237 return -ENODEV;
238 ccw_device_set_timeout(cdev, expires);
239 ret = ccw_device_start_key(cdev, cpa, intparm, lpm, key, flags);
240 if (ret != 0)
241 ccw_device_set_timeout(cdev, 0);
242 return ret;
243}
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
269 unsigned long intparm, __u8 lpm, unsigned long flags)
270{
271 return ccw_device_start_key(cdev, cpa, intparm, lpm,
272 PAGE_DEFAULT_KEY, flags);
273}
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
304 unsigned long intparm, __u8 lpm,
305 unsigned long flags, int expires)
306{
307 return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
308 PAGE_DEFAULT_KEY, flags,
309 expires);
310}
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
330{
331 struct subchannel *sch;
332 int ret;
333
334 if (!cdev)
335 return -ENODEV;
336 if (cdev->private->state == DEV_STATE_NOT_OPER)
337 return -ENODEV;
338 if (cdev->private->state != DEV_STATE_ONLINE &&
339 cdev->private->state != DEV_STATE_W4SENSE)
340 return -EINVAL;
341 sch = to_subchannel(cdev->dev.parent);
342 if (!sch)
343 return -ENODEV;
344 ret = cio_halt(sch);
345 if (ret == 0)
346 cdev->private->intparm = intparm;
347 return ret;
348}
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363int ccw_device_resume(struct ccw_device *cdev)
364{
365 struct subchannel *sch;
366
367 if (!cdev)
368 return -ENODEV;
369 sch = to_subchannel(cdev->dev.parent);
370 if (!sch)
371 return -ENODEV;
372 if (cdev->private->state == DEV_STATE_NOT_OPER)
373 return -ENODEV;
374 if (cdev->private->state != DEV_STATE_ONLINE ||
375 !(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED))
376 return -EINVAL;
377 return cio_resume(sch);
378}
379
380
381
382
383int
384ccw_device_call_handler(struct ccw_device *cdev)
385{
386 struct subchannel *sch;
387 unsigned int stctl;
388 int ending_status;
389
390 sch = to_subchannel(cdev->dev.parent);
391
392
393
394
395
396
397
398
399
400 stctl = cdev->private->irb.scsw.stctl;
401 ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
402 (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
403 (stctl == SCSW_STCTL_STATUS_PEND);
404 if (!ending_status &&
405 !cdev->private->options.repall &&
406 !(stctl & SCSW_STCTL_INTER_STATUS) &&
407 !(cdev->private->options.fast &&
408 (stctl & SCSW_STCTL_PRIM_STATUS)))
409 return 0;
410
411
412 if (ending_status)
413 ccw_device_set_timeout(cdev, 0);
414
415
416
417 if (cdev->handler)
418 cdev->handler(cdev, cdev->private->intparm,
419 &cdev->private->irb);
420
421
422
423
424 memset(&cdev->private->irb, 0, sizeof(struct irb));
425
426 return 1;
427}
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
444{
445 int ciw_cnt;
446
447 if (cdev->private->flags.esid == 0)
448 return NULL;
449 for (ciw_cnt = 0; ciw_cnt < MAX_CIWS; ciw_cnt++)
450 if (cdev->private->senseid.ciw[ciw_cnt].ct == ct)
451 return cdev->private->senseid.ciw + ciw_cnt;
452 return NULL;
453}
454
455
456
457
458
459
460
461
462__u8 ccw_device_get_path_mask(struct ccw_device *cdev)
463{
464 struct subchannel *sch;
465
466 sch = to_subchannel(cdev->dev.parent);
467 if (!sch)
468 return 0;
469 else
470 return sch->lpm;
471}
472
473
474
475
476int
477ccw_device_stlck(struct ccw_device *cdev)
478{
479 void *buf, *buf2;
480 unsigned long flags;
481 struct subchannel *sch;
482 int ret;
483
484 if (!cdev)
485 return -ENODEV;
486
487 if (cdev->drv && !cdev->private->options.force)
488 return -EINVAL;
489
490 sch = to_subchannel(cdev->dev.parent);
491
492 CIO_TRACE_EVENT(2, "stl lock");
493 CIO_TRACE_EVENT(2, cdev->dev.bus_id);
494
495 buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
496 if (!buf)
497 return -ENOMEM;
498 buf2 = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
499 if (!buf2) {
500 kfree(buf);
501 return -ENOMEM;
502 }
503 spin_lock_irqsave(sch->lock, flags);
504 ret = cio_enable_subchannel(sch, 3);
505 if (ret)
506 goto out_unlock;
507
508
509
510
511 cdev->private->iccws[0].cmd_code = CCW_CMD_STLCK;
512 cdev->private->iccws[0].cda = (__u32) __pa(buf);
513 cdev->private->iccws[0].count = 32;
514 cdev->private->iccws[0].flags = CCW_FLAG_CC;
515 cdev->private->iccws[1].cmd_code = CCW_CMD_RELEASE;
516 cdev->private->iccws[1].cda = (__u32) __pa(buf2);
517 cdev->private->iccws[1].count = 32;
518 cdev->private->iccws[1].flags = 0;
519 ret = cio_start(sch, cdev->private->iccws, 0);
520 if (ret) {
521 cio_disable_subchannel(sch);
522 goto out_unlock;
523 }
524 cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
525 spin_unlock_irqrestore(sch->lock, flags);
526 wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
527 spin_lock_irqsave(sch->lock, flags);
528 cio_disable_subchannel(sch);
529 if ((cdev->private->irb.scsw.dstat !=
530 (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
531 (cdev->private->irb.scsw.cstat != 0))
532 ret = -EIO;
533
534 memset(&cdev->private->irb, 0, sizeof(struct irb));
535out_unlock:
536 kfree(buf);
537 kfree(buf2);
538 spin_unlock_irqrestore(sch->lock, flags);
539 return ret;
540}
541
542void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
543{
544 struct subchannel *sch;
545 struct chp_id chpid;
546
547 sch = to_subchannel(cdev->dev.parent);
548 chp_id_init(&chpid);
549 chpid.id = sch->schib.pmcw.chpid[chp_no];
550 return chp_get_chp_desc(chpid);
551}
552
553
554
555
556
557
558void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
559{
560 *dev_id = cdev->private->dev_id;
561}
562EXPORT_SYMBOL(ccw_device_get_id);
563
564
565
566int
567_ccw_device_get_subchannel_number(struct ccw_device *cdev)
568{
569 return cdev->private->schid.sch_no;
570}
571
572
573MODULE_LICENSE("GPL");
574EXPORT_SYMBOL(ccw_device_set_options_mask);
575EXPORT_SYMBOL(ccw_device_set_options);
576EXPORT_SYMBOL(ccw_device_clear_options);
577EXPORT_SYMBOL(ccw_device_clear);
578EXPORT_SYMBOL(ccw_device_halt);
579EXPORT_SYMBOL(ccw_device_resume);
580EXPORT_SYMBOL(ccw_device_start_timeout);
581EXPORT_SYMBOL(ccw_device_start);
582EXPORT_SYMBOL(ccw_device_start_timeout_key);
583EXPORT_SYMBOL(ccw_device_start_key);
584EXPORT_SYMBOL(ccw_device_get_ciw);
585EXPORT_SYMBOL(ccw_device_get_path_mask);
586EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
587EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
588