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/smp_lock.h>
21#include <linux/err.h>
22
23#include <asm/uaccess.h>
24#include <asm/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
477 ccw = cqr->cpaddr;
478 ccw->cmd_code = DASD_ECKD_CCW_SNSS;
479 ccw->count = SNSS_DATA_SIZE;
480 ccw->flags = 0;
481 ccw->cda = (__u32)(addr_t) cqr->data;
482
483 cqr->buildclk = get_clock();
484 cqr->status = DASD_CQR_FILLED;
485 cqr->callback = dasd_eer_snss_cb;
486
487 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
488 if (!device->eer_cqr) {
489 device->eer_cqr = cqr;
490 cqr = NULL;
491 }
492 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
493 if (cqr)
494 dasd_kfree_request(cqr, device);
495 return 0;
496}
497
498
499
500
501void dasd_eer_disable(struct dasd_device *device)
502{
503 struct dasd_ccw_req *cqr;
504 unsigned long flags;
505 int in_use;
506
507 if (!device->eer_cqr)
508 return;
509 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
510 cqr = device->eer_cqr;
511 device->eer_cqr = NULL;
512 clear_bit(DASD_FLAG_EER_SNSS, &device->flags);
513 in_use = test_and_clear_bit(DASD_FLAG_EER_IN_USE, &device->flags);
514 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
515 if (cqr && !in_use)
516 dasd_kfree_request(cqr, device);
517}
518
519
520
521
522
523
524
525
526
527
528static char readbuffer[PAGE_SIZE];
529static DEFINE_MUTEX(readbuffer_mutex);
530
531static int dasd_eer_open(struct inode *inp, struct file *filp)
532{
533 struct eerbuffer *eerb;
534 unsigned long flags;
535
536 eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL);
537 if (!eerb)
538 return -ENOMEM;
539 lock_kernel();
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 unlock_kernel();
548 return -EINVAL;
549 }
550 eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
551 eerb->buffer = kmalloc(eerb->buffer_page_count * sizeof(char *),
552 GFP_KERNEL);
553 if (!eerb->buffer) {
554 kfree(eerb);
555 unlock_kernel();
556 return -ENOMEM;
557 }
558 if (dasd_eer_allocate_buffer_pages(eerb->buffer,
559 eerb->buffer_page_count)) {
560 kfree(eerb->buffer);
561 kfree(eerb);
562 unlock_kernel();
563 return -ENOMEM;
564 }
565 filp->private_data = eerb;
566 spin_lock_irqsave(&bufferlock, flags);
567 list_add(&eerb->list, &bufferlist);
568 spin_unlock_irqrestore(&bufferlock, flags);
569
570 unlock_kernel();
571 return nonseekable_open(inp,filp);
572}
573
574static int dasd_eer_close(struct inode *inp, struct file *filp)
575{
576 struct eerbuffer *eerb;
577 unsigned long flags;
578
579 eerb = (struct eerbuffer *) filp->private_data;
580 spin_lock_irqsave(&bufferlock, flags);
581 list_del(&eerb->list);
582 spin_unlock_irqrestore(&bufferlock, flags);
583 dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
584 kfree(eerb->buffer);
585 kfree(eerb);
586
587 return 0;
588}
589
590static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
591 size_t count, loff_t *ppos)
592{
593 int tc,rc;
594 int tailcount,effective_count;
595 unsigned long flags;
596 struct eerbuffer *eerb;
597
598 eerb = (struct eerbuffer *) filp->private_data;
599 if (mutex_lock_interruptible(&readbuffer_mutex))
600 return -ERESTARTSYS;
601
602 spin_lock_irqsave(&bufferlock, flags);
603
604 if (eerb->residual < 0) {
605
606 eerb->residual = 0;
607 spin_unlock_irqrestore(&bufferlock, flags);
608 mutex_unlock(&readbuffer_mutex);
609 return -EIO;
610 } else if (eerb->residual > 0) {
611
612 effective_count = min(eerb->residual, (int) count);
613 eerb->residual -= effective_count;
614 } else {
615 tc = 0;
616 while (!tc) {
617 tc = dasd_eer_read_buffer(eerb, (char *) &tailcount,
618 sizeof(tailcount));
619 if (!tc) {
620
621 spin_unlock_irqrestore(&bufferlock, flags);
622 mutex_unlock(&readbuffer_mutex);
623 if (filp->f_flags & O_NONBLOCK)
624 return -EAGAIN;
625 rc = wait_event_interruptible(
626 dasd_eer_read_wait_queue,
627 eerb->head != eerb->tail);
628 if (rc)
629 return rc;
630 if (mutex_lock_interruptible(&readbuffer_mutex))
631 return -ERESTARTSYS;
632 spin_lock_irqsave(&bufferlock, flags);
633 }
634 }
635 WARN_ON(tc != sizeof(tailcount));
636 effective_count = min(tailcount,(int)count);
637 eerb->residual = tailcount - effective_count;
638 }
639
640 tc = dasd_eer_read_buffer(eerb, readbuffer, effective_count);
641 WARN_ON(tc != effective_count);
642
643 spin_unlock_irqrestore(&bufferlock, flags);
644
645 if (copy_to_user(buf, readbuffer, effective_count)) {
646 mutex_unlock(&readbuffer_mutex);
647 return -EFAULT;
648 }
649
650 mutex_unlock(&readbuffer_mutex);
651 return effective_count;
652}
653
654static unsigned int dasd_eer_poll(struct file *filp, poll_table *ptable)
655{
656 unsigned int mask;
657 unsigned long flags;
658 struct eerbuffer *eerb;
659
660 eerb = (struct eerbuffer *) filp->private_data;
661 poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
662 spin_lock_irqsave(&bufferlock, flags);
663 if (eerb->head != eerb->tail)
664 mask = POLLIN | POLLRDNORM ;
665 else
666 mask = 0;
667 spin_unlock_irqrestore(&bufferlock, flags);
668 return mask;
669}
670
671static const struct file_operations dasd_eer_fops = {
672 .open = &dasd_eer_open,
673 .release = &dasd_eer_close,
674 .read = &dasd_eer_read,
675 .poll = &dasd_eer_poll,
676 .owner = THIS_MODULE,
677};
678
679static struct miscdevice *dasd_eer_dev = NULL;
680
681int __init dasd_eer_init(void)
682{
683 int rc;
684
685 dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL);
686 if (!dasd_eer_dev)
687 return -ENOMEM;
688
689 dasd_eer_dev->minor = MISC_DYNAMIC_MINOR;
690 dasd_eer_dev->name = "dasd_eer";
691 dasd_eer_dev->fops = &dasd_eer_fops;
692
693 rc = misc_register(dasd_eer_dev);
694 if (rc) {
695 kfree(dasd_eer_dev);
696 dasd_eer_dev = NULL;
697 DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not "
698 "register misc device");
699 return rc;
700 }
701
702 return 0;
703}
704
705void dasd_eer_exit(void)
706{
707 if (dasd_eer_dev) {
708 WARN_ON(misc_deregister(dasd_eer_dev) != 0);
709 kfree(dasd_eer_dev);
710 dasd_eer_dev = NULL;
711 }
712}
713