1
2
3
4
5
6
7
8
9#define KMSG_COMPONENT "dasd-eckd"
10
11#include <linux/init.h>
12#include <linux/fs.h>
13#include <linux/kernel.h>
14#include <linux/miscdevice.h>
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/device.h>
18#include <linux/poll.h>
19#include <linux/mutex.h>
20#include <linux/err.h>
21#include <linux/slab.h>
22
23#include <asm/uaccess.h>
24#include <linux/atomic.h>
25#include <asm/ebcdic.h>
26
27#include "dasd_int.h"
28#include "dasd_eckd.h"
29
30#ifdef PRINTK_HEADER
31#undef PRINTK_HEADER
32#endif
33#define PRINTK_HEADER "dasd(eer):"
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82static int eer_pages = 5;
83module_param(eer_pages, int, S_IRUGO|S_IWUSR);
84
85struct eerbuffer {
86 struct list_head list;
87 char **buffer;
88 int buffersize;
89 int buffer_page_count;
90 int head;
91 int tail;
92 int residual;
93};
94
95static LIST_HEAD(bufferlist);
96static DEFINE_SPINLOCK(bufferlock);
97static DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
98
99
100
101
102
103static int dasd_eer_get_free_bytes(struct eerbuffer *eerb)
104{
105 if (eerb->head < eerb->tail)
106 return eerb->tail - eerb->head - 1;
107 return eerb->buffersize - eerb->head + eerb->tail -1;
108}
109
110
111
112
113
114static int dasd_eer_get_filled_bytes(struct eerbuffer *eerb)
115{
116
117 if (eerb->head >= eerb->tail)
118 return eerb->head - eerb->tail;
119 return eerb->buffersize - eerb->tail + eerb->head;
120}
121
122
123
124
125
126
127
128static void dasd_eer_write_buffer(struct eerbuffer *eerb,
129 char *data, int count)
130{
131
132 unsigned long headindex,localhead;
133 unsigned long rest, len;
134 char *nextdata;
135
136 nextdata = data;
137 rest = count;
138 while (rest > 0) {
139 headindex = eerb->head / PAGE_SIZE;
140 localhead = eerb->head % PAGE_SIZE;
141 len = min(rest, PAGE_SIZE - localhead);
142 memcpy(eerb->buffer[headindex]+localhead, nextdata, len);
143 nextdata += len;
144 rest -= len;
145 eerb->head += len;
146 if (eerb->head == eerb->buffersize)
147 eerb->head = 0;
148 BUG_ON(eerb->head > eerb->buffersize);
149 }
150}
151
152
153
154
155static int dasd_eer_read_buffer(struct eerbuffer *eerb, char *data, int count)
156{
157
158 unsigned long tailindex,localtail;
159 unsigned long rest, len, finalcount;
160 char *nextdata;
161
162 finalcount = min(count, dasd_eer_get_filled_bytes(eerb));
163 nextdata = data;
164 rest = finalcount;
165 while (rest > 0) {
166 tailindex = eerb->tail / PAGE_SIZE;
167 localtail = eerb->tail % PAGE_SIZE;
168 len = min(rest, PAGE_SIZE - localtail);
169 memcpy(nextdata, eerb->buffer[tailindex] + localtail, len);
170 nextdata += len;
171 rest -= len;
172 eerb->tail += len;
173 if (eerb->tail == eerb->buffersize)
174 eerb->tail = 0;
175 BUG_ON(eerb->tail > eerb->buffersize);
176 }
177 return finalcount;
178}
179
180
181
182
183
184
185
186
187static int dasd_eer_start_record(struct eerbuffer *eerb, int count)
188{
189 int tailcount;
190
191 if (count + sizeof(count) > eerb->buffersize)
192 return -ENOMEM;
193 while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) {
194 if (eerb->residual > 0) {
195 eerb->tail += eerb->residual;
196 if (eerb->tail >= eerb->buffersize)
197 eerb->tail -= eerb->buffersize;
198 eerb->residual = -1;
199 }
200 dasd_eer_read_buffer(eerb, (char *) &tailcount,
201 sizeof(tailcount));
202 eerb->tail += tailcount;
203 if (eerb->tail >= eerb->buffersize)
204 eerb->tail -= eerb->buffersize;
205 }
206 dasd_eer_write_buffer(eerb, (char*) &count, sizeof(count));
207
208 return 0;
209};
210
211
212
213
214static void dasd_eer_free_buffer_pages(char **buf, int no_pages)
215{
216 int i;
217
218 for (i = 0; i < no_pages; i++)
219 free_page((unsigned long) buf[i]);
220}
221
222
223
224
225static int dasd_eer_allocate_buffer_pages(char **buf, int no_pages)
226{
227 int i;
228
229 for (i = 0; i < no_pages; i++) {
230 buf[i] = (char *) get_zeroed_page(GFP_KERNEL);
231 if (!buf[i]) {
232 dasd_eer_free_buffer_pages(buf, i);
233 return -ENOMEM;
234 }
235 }
236 return 0;
237}
238
239
240
241
242
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
268
269
270
271
272
273
274#define SNSS_DATA_SIZE 44
275
276#define DASD_EER_BUSID_SIZE 10
277struct dasd_eer_header {
278 __u32 total_size;
279 __u32 trigger;
280 __u64 tv_sec;
281 __u64 tv_usec;
282 char busid[DASD_EER_BUSID_SIZE];
283} __attribute__ ((packed));
284
285
286
287
288
289
290
291
292static void dasd_eer_write_standard_trigger(struct dasd_device *device,
293 struct dasd_ccw_req *cqr,
294 int trigger)
295{
296 struct dasd_ccw_req *temp_cqr;
297 int data_size;
298 struct timeval tv;
299 struct dasd_eer_header header;
300 unsigned long flags;
301 struct eerbuffer *eerb;
302 char *sense;
303
304
305 data_size = 0;
306 for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers)
307 if (dasd_get_sense(&temp_cqr->irb))
308 data_size += 32;
309
310 header.total_size = sizeof(header) + data_size + 4;
311 header.trigger = trigger;
312 do_gettimeofday(&tv);
313 header.tv_sec = tv.tv_sec;
314 header.tv_usec = tv.tv_usec;
315 strncpy(header.busid, dev_name(&device->cdev->dev),
316 DASD_EER_BUSID_SIZE);
317
318 spin_lock_irqsave(&bufferlock, flags);
319 list_for_each_entry(eerb, &bufferlist, list) {
320 dasd_eer_start_record(eerb, header.total_size);
321 dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header));
322 for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) {
323 sense = dasd_get_sense(&temp_cqr->irb);
324 if (sense)
325 dasd_eer_write_buffer(eerb, sense, 32);
326 }
327 dasd_eer_write_buffer(eerb, "EOR", 4);
328 }
329 spin_unlock_irqrestore(&bufferlock, flags);
330 wake_up_interruptible(&dasd_eer_read_wait_queue);
331}
332
333
334
335
336static void dasd_eer_write_snss_trigger(struct dasd_device *device,
337 struct dasd_ccw_req *cqr,
338 int trigger)
339{
340 int data_size;
341 int snss_rc;
342 struct timeval tv;
343 struct dasd_eer_header header;
344 unsigned long flags;
345 struct eerbuffer *eerb;
346
347 snss_rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
348 if (snss_rc)
349 data_size = 0;
350 else
351 data_size = SNSS_DATA_SIZE;
352
353 header.total_size = sizeof(header) + data_size + 4;
354 header.trigger = DASD_EER_STATECHANGE;
355 do_gettimeofday(&tv);
356 header.tv_sec = tv.tv_sec;
357 header.tv_usec = tv.tv_usec;
358 strncpy(header.busid, dev_name(&device->cdev->dev),
359 DASD_EER_BUSID_SIZE);
360
361 spin_lock_irqsave(&bufferlock, flags);
362 list_for_each_entry(eerb, &bufferlist, list) {
363 dasd_eer_start_record(eerb, header.total_size);
364 dasd_eer_write_buffer(eerb, (char *) &header , sizeof(header));
365 if (!snss_rc)
366 dasd_eer_write_buffer(eerb, cqr->data, SNSS_DATA_SIZE);
367 dasd_eer_write_buffer(eerb, "EOR", 4);
368 }
369 spin_unlock_irqrestore(&bufferlock, flags);
370 wake_up_interruptible(&dasd_eer_read_wait_queue);
371}
372
373
374
375
376
377void dasd_eer_write(struct dasd_device *device, struct dasd_ccw_req *cqr,
378 unsigned int id)
379{
380 if (!device->eer_cqr)
381 return;
382 switch (id) {
383 case DASD_EER_FATALERROR:
384 case DASD_EER_PPRCSUSPEND:
385 dasd_eer_write_standard_trigger(device, cqr, id);
386 break;
387 case DASD_EER_NOPATH:
388 dasd_eer_write_standard_trigger(device, NULL, id);
389 break;
390 case DASD_EER_STATECHANGE:
391 dasd_eer_write_snss_trigger(device, cqr, id);
392 break;
393 default:
394 dasd_eer_write_standard_trigger(device, NULL, id);
395 break;
396 }
397}
398EXPORT_SYMBOL(dasd_eer_write);
399
400
401
402
403
404void dasd_eer_snss(struct dasd_device *device)
405{
406 struct dasd_ccw_req *cqr;
407
408 cqr = device->eer_cqr;
409 if (!cqr)
410 return;
411 if (test_and_set_bit(DASD_FLAG_EER_IN_USE, &device->flags)) {
412
413 set_bit(DASD_FLAG_EER_SNSS, &device->flags);
414 return;
415 }
416
417 clear_bit(DASD_FLAG_EER_SNSS, &device->flags);
418 cqr->status = DASD_CQR_QUEUED;
419 list_add(&cqr->devlist, &device->ccw_queue);
420 dasd_schedule_device_bh(device);
421}
422
423
424
425
426static void dasd_eer_snss_cb(struct dasd_ccw_req *cqr, void *data)
427{
428 struct dasd_device *device = cqr->startdev;
429 unsigned long flags;
430
431 dasd_eer_write(device, cqr, DASD_EER_STATECHANGE);
432 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
433 if (device->eer_cqr == cqr) {
434 clear_bit(DASD_FLAG_EER_IN_USE, &device->flags);
435 if (test_bit(DASD_FLAG_EER_SNSS, &device->flags))
436
437 dasd_eer_snss(device);
438 cqr = NULL;
439 }
440 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
441 if (cqr)
442
443
444
445
446
447
448
449 dasd_kfree_request(cqr, device);
450}
451
452
453
454
455int dasd_eer_enable(struct dasd_device *device)
456{
457 struct dasd_ccw_req *cqr;
458 unsigned long flags;
459 struct ccw1 *ccw;
460
461 if (device->eer_cqr)
462 return 0;
463
464 if (!device->discipline || strcmp(device->discipline->name, "ECKD"))
465 return -EPERM;
466
467 cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 ,
468 SNSS_DATA_SIZE, device);
469 if (IS_ERR(cqr))
470 return -ENOMEM;
471
472 cqr->startdev = device;
473 cqr->retries = 255;
474 cqr->expires = 10 * HZ;
475 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
476 set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
477
478 ccw = cqr->cpaddr;
479 ccw->cmd_code = DASD_ECKD_CCW_SNSS;
480 ccw->count = SNSS_DATA_SIZE;
481 ccw->flags = 0;
482 ccw->cda = (__u32)(addr_t) cqr->data;
483
484 cqr->buildclk = get_clock();
485 cqr->status = DASD_CQR_FILLED;
486 cqr->callback = dasd_eer_snss_cb;
487
488 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
489 if (!device->eer_cqr) {
490 device->eer_cqr = cqr;
491 cqr = NULL;
492 }
493 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
494 if (cqr)
495 dasd_kfree_request(cqr, device);
496 return 0;
497}
498
499
500
501
502void dasd_eer_disable(struct dasd_device *device)
503{
504 struct dasd_ccw_req *cqr;
505 unsigned long flags;
506 int in_use;
507
508 if (!device->eer_cqr)
509 return;
510 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
511 cqr = device->eer_cqr;
512 device->eer_cqr = NULL;
513 clear_bit(DASD_FLAG_EER_SNSS, &device->flags);
514 in_use = test_and_clear_bit(DASD_FLAG_EER_IN_USE, &device->flags);
515 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
516 if (cqr && !in_use)
517 dasd_kfree_request(cqr, device);
518}
519
520
521
522
523
524
525
526
527
528
529static char readbuffer[PAGE_SIZE];
530static DEFINE_MUTEX(readbuffer_mutex);
531
532static int dasd_eer_open(struct inode *inp, struct file *filp)
533{
534 struct eerbuffer *eerb;
535 unsigned long flags;
536
537 eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL);
538 if (!eerb)
539 return -ENOMEM;
540 eerb->buffer_page_count = eer_pages;
541 if (eerb->buffer_page_count < 1 ||
542 eerb->buffer_page_count > INT_MAX / PAGE_SIZE) {
543 kfree(eerb);
544 DBF_EVENT(DBF_WARNING, "can't open device since module "
545 "parameter eer_pages is smaller than 1 or"
546 " bigger than %d", (int)(INT_MAX / PAGE_SIZE));
547 return -EINVAL;
548 }
549 eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
550 eerb->buffer = kmalloc(eerb->buffer_page_count * sizeof(char *),
551 GFP_KERNEL);
552 if (!eerb->buffer) {
553 kfree(eerb);
554 return -ENOMEM;
555 }
556 if (dasd_eer_allocate_buffer_pages(eerb->buffer,
557 eerb->buffer_page_count)) {
558 kfree(eerb->buffer);
559 kfree(eerb);
560 return -ENOMEM;
561 }
562 filp->private_data = eerb;
563 spin_lock_irqsave(&bufferlock, flags);
564 list_add(&eerb->list, &bufferlist);
565 spin_unlock_irqrestore(&bufferlock, flags);
566
567 return nonseekable_open(inp,filp);
568}
569
570static int dasd_eer_close(struct inode *inp, struct file *filp)
571{
572 struct eerbuffer *eerb;
573 unsigned long flags;
574
575 eerb = (struct eerbuffer *) filp->private_data;
576 spin_lock_irqsave(&bufferlock, flags);
577 list_del(&eerb->list);
578 spin_unlock_irqrestore(&bufferlock, flags);
579 dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
580 kfree(eerb->buffer);
581 kfree(eerb);
582
583 return 0;
584}
585
586static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
587 size_t count, loff_t *ppos)
588{
589 int tc,rc;
590 int tailcount,effective_count;
591 unsigned long flags;
592 struct eerbuffer *eerb;
593
594 eerb = (struct eerbuffer *) filp->private_data;
595 if (mutex_lock_interruptible(&readbuffer_mutex))
596 return -ERESTARTSYS;
597
598 spin_lock_irqsave(&bufferlock, flags);
599
600 if (eerb->residual < 0) {
601
602 eerb->residual = 0;
603 spin_unlock_irqrestore(&bufferlock, flags);
604 mutex_unlock(&readbuffer_mutex);
605 return -EIO;
606 } else if (eerb->residual > 0) {
607
608 effective_count = min(eerb->residual, (int) count);
609 eerb->residual -= effective_count;
610 } else {
611 tc = 0;
612 while (!tc) {
613 tc = dasd_eer_read_buffer(eerb, (char *) &tailcount,
614 sizeof(tailcount));
615 if (!tc) {
616
617 spin_unlock_irqrestore(&bufferlock, flags);
618 mutex_unlock(&readbuffer_mutex);
619 if (filp->f_flags & O_NONBLOCK)
620 return -EAGAIN;
621 rc = wait_event_interruptible(
622 dasd_eer_read_wait_queue,
623 eerb->head != eerb->tail);
624 if (rc)
625 return rc;
626 if (mutex_lock_interruptible(&readbuffer_mutex))
627 return -ERESTARTSYS;
628 spin_lock_irqsave(&bufferlock, flags);
629 }
630 }
631 WARN_ON(tc != sizeof(tailcount));
632 effective_count = min(tailcount,(int)count);
633 eerb->residual = tailcount - effective_count;
634 }
635
636 tc = dasd_eer_read_buffer(eerb, readbuffer, effective_count);
637 WARN_ON(tc != effective_count);
638
639 spin_unlock_irqrestore(&bufferlock, flags);
640
641 if (copy_to_user(buf, readbuffer, effective_count)) {
642 mutex_unlock(&readbuffer_mutex);
643 return -EFAULT;
644 }
645
646 mutex_unlock(&readbuffer_mutex);
647 return effective_count;
648}
649
650static unsigned int dasd_eer_poll(struct file *filp, poll_table *ptable)
651{
652 unsigned int mask;
653 unsigned long flags;
654 struct eerbuffer *eerb;
655
656 eerb = (struct eerbuffer *) filp->private_data;
657 poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
658 spin_lock_irqsave(&bufferlock, flags);
659 if (eerb->head != eerb->tail)
660 mask = POLLIN | POLLRDNORM ;
661 else
662 mask = 0;
663 spin_unlock_irqrestore(&bufferlock, flags);
664 return mask;
665}
666
667static const struct file_operations dasd_eer_fops = {
668 .open = &dasd_eer_open,
669 .release = &dasd_eer_close,
670 .read = &dasd_eer_read,
671 .poll = &dasd_eer_poll,
672 .owner = THIS_MODULE,
673 .llseek = noop_llseek,
674};
675
676static struct miscdevice *dasd_eer_dev = NULL;
677
678int __init dasd_eer_init(void)
679{
680 int rc;
681
682 dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL);
683 if (!dasd_eer_dev)
684 return -ENOMEM;
685
686 dasd_eer_dev->minor = MISC_DYNAMIC_MINOR;
687 dasd_eer_dev->name = "dasd_eer";
688 dasd_eer_dev->fops = &dasd_eer_fops;
689
690 rc = misc_register(dasd_eer_dev);
691 if (rc) {
692 kfree(dasd_eer_dev);
693 dasd_eer_dev = NULL;
694 DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not "
695 "register misc device");
696 return rc;
697 }
698
699 return 0;
700}
701
702void dasd_eer_exit(void)
703{
704 if (dasd_eer_dev) {
705 misc_deregister(dasd_eer_dev);
706 kfree(dasd_eer_dev);
707 dasd_eer_dev = NULL;
708 }
709}
710