1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <linux/io.h>
46#include <linux/pci.h>
47#include <linux/poll.h>
48#include <linux/vmalloc.h>
49#include <linux/export.h>
50#include <linux/fs.h>
51#include <linux/uaccess.h>
52
53#include "qib.h"
54#include "qib_common.h"
55
56#undef pr_fmt
57#define pr_fmt(fmt) QIB_DRV_NAME ": " fmt
58
59
60
61
62
63
64enum diag_state { UNUSED = 0, OPENED, INIT, READY };
65
66
67static struct qib_diag_client {
68 struct qib_diag_client *next;
69 struct qib_devdata *dd;
70 pid_t pid;
71 enum diag_state state;
72} *client_pool;
73
74
75
76
77
78static struct qib_diag_client *get_client(struct qib_devdata *dd)
79{
80 struct qib_diag_client *dc;
81
82 dc = client_pool;
83 if (dc)
84
85 client_pool = dc->next;
86 else
87
88 dc = kmalloc(sizeof(*dc), GFP_KERNEL);
89
90 if (dc) {
91 dc->next = NULL;
92 dc->dd = dd;
93 dc->pid = current->pid;
94 dc->state = OPENED;
95 }
96 return dc;
97}
98
99
100
101
102static void return_client(struct qib_diag_client *dc)
103{
104 struct qib_devdata *dd = dc->dd;
105 struct qib_diag_client *tdc, *rdc;
106
107 rdc = NULL;
108 if (dc == dd->diag_client) {
109 dd->diag_client = dc->next;
110 rdc = dc;
111 } else {
112 tdc = dc->dd->diag_client;
113 while (tdc) {
114 if (dc == tdc->next) {
115 tdc->next = dc->next;
116 rdc = dc;
117 break;
118 }
119 tdc = tdc->next;
120 }
121 }
122 if (rdc) {
123 rdc->state = UNUSED;
124 rdc->dd = NULL;
125 rdc->pid = 0;
126 rdc->next = client_pool;
127 client_pool = rdc;
128 }
129}
130
131static int qib_diag_open(struct inode *in, struct file *fp);
132static int qib_diag_release(struct inode *in, struct file *fp);
133static ssize_t qib_diag_read(struct file *fp, char __user *data,
134 size_t count, loff_t *off);
135static ssize_t qib_diag_write(struct file *fp, const char __user *data,
136 size_t count, loff_t *off);
137
138static const struct file_operations diag_file_ops = {
139 .owner = THIS_MODULE,
140 .write = qib_diag_write,
141 .read = qib_diag_read,
142 .open = qib_diag_open,
143 .release = qib_diag_release,
144 .llseek = default_llseek,
145};
146
147static atomic_t diagpkt_count = ATOMIC_INIT(0);
148static struct cdev *diagpkt_cdev;
149static struct device *diagpkt_device;
150
151static ssize_t qib_diagpkt_write(struct file *fp, const char __user *data,
152 size_t count, loff_t *off);
153
154static const struct file_operations diagpkt_file_ops = {
155 .owner = THIS_MODULE,
156 .write = qib_diagpkt_write,
157 .llseek = noop_llseek,
158};
159
160int qib_diag_add(struct qib_devdata *dd)
161{
162 char name[16];
163 int ret = 0;
164
165 if (atomic_inc_return(&diagpkt_count) == 1) {
166 ret = qib_cdev_init(QIB_DIAGPKT_MINOR, "ipath_diagpkt",
167 &diagpkt_file_ops, &diagpkt_cdev,
168 &diagpkt_device);
169 if (ret)
170 goto done;
171 }
172
173 snprintf(name, sizeof(name), "ipath_diag%d", dd->unit);
174 ret = qib_cdev_init(QIB_DIAG_MINOR_BASE + dd->unit, name,
175 &diag_file_ops, &dd->diag_cdev,
176 &dd->diag_device);
177done:
178 return ret;
179}
180
181static void qib_unregister_observers(struct qib_devdata *dd);
182
183void qib_diag_remove(struct qib_devdata *dd)
184{
185 struct qib_diag_client *dc;
186
187 if (atomic_dec_and_test(&diagpkt_count))
188 qib_cdev_cleanup(&diagpkt_cdev, &diagpkt_device);
189
190 qib_cdev_cleanup(&dd->diag_cdev, &dd->diag_device);
191
192
193
194
195
196 while (dd->diag_client)
197 return_client(dd->diag_client);
198
199
200 while (client_pool) {
201 dc = client_pool;
202 client_pool = dc->next;
203 kfree(dc);
204 }
205
206 qib_unregister_observers(dd);
207}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
235 u32 *cntp)
236{
237 u32 kreglen;
238 u32 snd_bottom, snd_lim = 0;
239 u32 __iomem *krb32 = (u32 __iomem *)dd->kregbase;
240 u32 __iomem *map = NULL;
241 u32 cnt = 0;
242 u32 tot4k, offs4k;
243
244
245 kreglen = (dd->kregend - dd->kregbase) * sizeof(u64);
246 if (offset < kreglen) {
247 map = krb32 + (offset / sizeof(u32));
248 cnt = kreglen - offset;
249 goto mapped;
250 }
251
252
253
254
255
256
257 if (dd->userbase) {
258
259 u32 ulim = (dd->cfgctxts * dd->ureg_align) + dd->uregbase;
260
261 if (!dd->piovl15base)
262 snd_lim = dd->uregbase;
263 krb32 = (u32 __iomem *)dd->userbase;
264 if (offset >= dd->uregbase && offset < ulim) {
265 map = krb32 + (offset - dd->uregbase) / sizeof(u32);
266 cnt = ulim - offset;
267 goto mapped;
268 }
269 }
270
271
272
273
274
275
276
277
278
279
280
281 snd_bottom = dd->pio2k_bufbase;
282 if (snd_lim == 0) {
283 u32 tot2k = dd->piobcnt2k * ALIGN(dd->piosize2k, dd->palign);
284
285 snd_lim = snd_bottom + tot2k;
286 }
287
288
289
290 tot4k = dd->piobcnt4k * dd->align4k;
291 offs4k = dd->piobufbase >> 32;
292 if (dd->piobcnt4k) {
293 if (snd_bottom > offs4k)
294 snd_bottom = offs4k;
295 else {
296
297 if (!dd->userbase || dd->piovl15base)
298 snd_lim = offs4k + tot4k;
299 }
300 }
301
302
303
304
305 if (offset >= snd_bottom && offset < snd_lim) {
306 offset -= snd_bottom;
307 map = (u32 __iomem *)dd->piobase + (offset / sizeof(u32));
308 cnt = snd_lim - offset;
309 }
310
311 if (!map && offs4k && dd->piovl15base) {
312 snd_lim = offs4k + tot4k + 2 * dd->align4k;
313 if (offset >= (offs4k + tot4k) && offset < snd_lim) {
314 map = (u32 __iomem *)dd->piovl15base +
315 ((offset - (offs4k + tot4k)) / sizeof(u32));
316 cnt = snd_lim - offset;
317 }
318 }
319
320mapped:
321 if (cntp)
322 *cntp = cnt;
323 return map;
324}
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339static int qib_read_umem64(struct qib_devdata *dd, void __user *uaddr,
340 u32 regoffs, size_t count)
341{
342 const u64 __iomem *reg_addr;
343 const u64 __iomem *reg_end;
344 u32 limit;
345 int ret;
346
347 reg_addr = (const u64 __iomem *)qib_remap_ioaddr32(dd, regoffs, &limit);
348 if (reg_addr == NULL || limit == 0 || !(dd->flags & QIB_PRESENT)) {
349 ret = -EINVAL;
350 goto bail;
351 }
352 if (count >= limit)
353 count = limit;
354 reg_end = reg_addr + (count / sizeof(u64));
355
356
357 while (reg_addr < reg_end) {
358 u64 data = readq(reg_addr);
359
360 if (copy_to_user(uaddr, &data, sizeof(u64))) {
361 ret = -EFAULT;
362 goto bail;
363 }
364 reg_addr++;
365 uaddr += sizeof(u64);
366 }
367 ret = 0;
368bail:
369 return ret;
370}
371
372
373
374
375
376
377
378
379
380
381
382
383static int qib_write_umem64(struct qib_devdata *dd, u32 regoffs,
384 const void __user *uaddr, size_t count)
385{
386 u64 __iomem *reg_addr;
387 const u64 __iomem *reg_end;
388 u32 limit;
389 int ret;
390
391 reg_addr = (u64 __iomem *)qib_remap_ioaddr32(dd, regoffs, &limit);
392 if (reg_addr == NULL || limit == 0 || !(dd->flags & QIB_PRESENT)) {
393 ret = -EINVAL;
394 goto bail;
395 }
396 if (count >= limit)
397 count = limit;
398 reg_end = reg_addr + (count / sizeof(u64));
399
400
401 while (reg_addr < reg_end) {
402 u64 data;
403
404 if (copy_from_user(&data, uaddr, sizeof(data))) {
405 ret = -EFAULT;
406 goto bail;
407 }
408 writeq(data, reg_addr);
409
410 reg_addr++;
411 uaddr += sizeof(u64);
412 }
413 ret = 0;
414bail:
415 return ret;
416}
417
418
419
420
421
422
423
424
425
426
427
428static int qib_read_umem32(struct qib_devdata *dd, void __user *uaddr,
429 u32 regoffs, size_t count)
430{
431 const u32 __iomem *reg_addr;
432 const u32 __iomem *reg_end;
433 u32 limit;
434 int ret;
435
436 reg_addr = qib_remap_ioaddr32(dd, regoffs, &limit);
437 if (reg_addr == NULL || limit == 0 || !(dd->flags & QIB_PRESENT)) {
438 ret = -EINVAL;
439 goto bail;
440 }
441 if (count >= limit)
442 count = limit;
443 reg_end = reg_addr + (count / sizeof(u32));
444
445
446 while (reg_addr < reg_end) {
447 u32 data = readl(reg_addr);
448
449 if (copy_to_user(uaddr, &data, sizeof(data))) {
450 ret = -EFAULT;
451 goto bail;
452 }
453
454 reg_addr++;
455 uaddr += sizeof(u32);
456
457 }
458 ret = 0;
459bail:
460 return ret;
461}
462
463
464
465
466
467
468
469
470
471
472
473
474static int qib_write_umem32(struct qib_devdata *dd, u32 regoffs,
475 const void __user *uaddr, size_t count)
476{
477 u32 __iomem *reg_addr;
478 const u32 __iomem *reg_end;
479 u32 limit;
480 int ret;
481
482 reg_addr = qib_remap_ioaddr32(dd, regoffs, &limit);
483 if (reg_addr == NULL || limit == 0 || !(dd->flags & QIB_PRESENT)) {
484 ret = -EINVAL;
485 goto bail;
486 }
487 if (count >= limit)
488 count = limit;
489 reg_end = reg_addr + (count / sizeof(u32));
490
491 while (reg_addr < reg_end) {
492 u32 data;
493
494 if (copy_from_user(&data, uaddr, sizeof(data))) {
495 ret = -EFAULT;
496 goto bail;
497 }
498 writel(data, reg_addr);
499
500 reg_addr++;
501 uaddr += sizeof(u32);
502 }
503 ret = 0;
504bail:
505 return ret;
506}
507
508static int qib_diag_open(struct inode *in, struct file *fp)
509{
510 int unit = iminor(in) - QIB_DIAG_MINOR_BASE;
511 struct qib_devdata *dd;
512 struct qib_diag_client *dc;
513 int ret;
514
515 mutex_lock(&qib_mutex);
516
517 dd = qib_lookup(unit);
518
519 if (dd == NULL || !(dd->flags & QIB_PRESENT) ||
520 !dd->kregbase) {
521 ret = -ENODEV;
522 goto bail;
523 }
524
525 dc = get_client(dd);
526 if (!dc) {
527 ret = -ENOMEM;
528 goto bail;
529 }
530 dc->next = dd->diag_client;
531 dd->diag_client = dc;
532 fp->private_data = dc;
533 ret = 0;
534bail:
535 mutex_unlock(&qib_mutex);
536
537 return ret;
538}
539
540
541
542
543
544
545
546
547static ssize_t qib_diagpkt_write(struct file *fp,
548 const char __user *data,
549 size_t count, loff_t *off)
550{
551 u32 __iomem *piobuf;
552 u32 plen, pbufn, maxlen_reserve;
553 struct qib_diag_xpkt dp;
554 u32 *tmpbuf = NULL;
555 struct qib_devdata *dd;
556 struct qib_pportdata *ppd;
557 ssize_t ret = 0;
558
559 if (count != sizeof(dp)) {
560 ret = -EINVAL;
561 goto bail;
562 }
563 if (copy_from_user(&dp, data, sizeof(dp))) {
564 ret = -EFAULT;
565 goto bail;
566 }
567
568 dd = qib_lookup(dp.unit);
569 if (!dd || !(dd->flags & QIB_PRESENT) || !dd->kregbase) {
570 ret = -ENODEV;
571 goto bail;
572 }
573 if (!(dd->flags & QIB_INITTED)) {
574
575 ret = -ENODEV;
576 goto bail;
577 }
578
579 if (dp.version != _DIAG_XPKT_VERS) {
580 qib_dev_err(dd, "Invalid version %u for diagpkt_write\n",
581 dp.version);
582 ret = -EINVAL;
583 goto bail;
584 }
585
586 if (dp.len & 3) {
587 ret = -EINVAL;
588 goto bail;
589 }
590 if (!dp.port || dp.port > dd->num_pports) {
591 ret = -EINVAL;
592 goto bail;
593 }
594 ppd = &dd->pport[dp.port - 1];
595
596
597
598
599
600
601
602 maxlen_reserve = 2 * sizeof(u32);
603 if (dp.len > ppd->ibmaxlen - maxlen_reserve) {
604 ret = -EINVAL;
605 goto bail;
606 }
607
608 plen = sizeof(u32) + dp.len;
609
610 tmpbuf = vmalloc(plen);
611 if (!tmpbuf) {
612 ret = -ENOMEM;
613 goto bail;
614 }
615
616 if (copy_from_user(tmpbuf,
617 u64_to_user_ptr(dp.data),
618 dp.len)) {
619 ret = -EFAULT;
620 goto bail;
621 }
622
623 plen >>= 2;
624
625 if (dp.pbc_wd == 0)
626 dp.pbc_wd = plen;
627
628 piobuf = dd->f_getsendbuf(ppd, dp.pbc_wd, &pbufn);
629 if (!piobuf) {
630 ret = -EBUSY;
631 goto bail;
632 }
633
634 dd->f_sendctrl(dd->pport, QIB_SENDCTRL_DISARM_BUF(pbufn));
635
636
637 dd->f_txchk_change(dd, pbufn, 1, TXCHK_CHG_TYPE_DIS1, NULL);
638
639 writeq(dp.pbc_wd, piobuf);
640
641
642
643
644
645 if (dd->flags & QIB_PIO_FLUSH_WC) {
646 qib_flush_wc();
647 qib_pio_copy(piobuf + 2, tmpbuf, plen - 1);
648 qib_flush_wc();
649 __raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);
650 } else
651 qib_pio_copy(piobuf + 2, tmpbuf, plen);
652
653 if (dd->flags & QIB_USE_SPCL_TRIG) {
654 u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023;
655
656 qib_flush_wc();
657 __raw_writel(0xaebecede, piobuf + spcl_off);
658 }
659
660
661
662
663
664
665 qib_flush_wc();
666 qib_sendbuf_done(dd, pbufn);
667 dd->f_txchk_change(dd, pbufn, 1, TXCHK_CHG_TYPE_ENAB1, NULL);
668
669 ret = sizeof(dp);
670
671bail:
672 vfree(tmpbuf);
673 return ret;
674}
675
676static int qib_diag_release(struct inode *in, struct file *fp)
677{
678 mutex_lock(&qib_mutex);
679 return_client(fp->private_data);
680 fp->private_data = NULL;
681 mutex_unlock(&qib_mutex);
682 return 0;
683}
684
685
686
687
688
689struct diag_observer_list_elt {
690 struct diag_observer_list_elt *next;
691 const struct diag_observer *op;
692};
693
694int qib_register_observer(struct qib_devdata *dd,
695 const struct diag_observer *op)
696{
697 struct diag_observer_list_elt *olp;
698 unsigned long flags;
699
700 if (!dd || !op)
701 return -EINVAL;
702 olp = vmalloc(sizeof(*olp));
703 if (!olp)
704 return -ENOMEM;
705
706 spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
707 olp->op = op;
708 olp->next = dd->diag_observer_list;
709 dd->diag_observer_list = olp;
710 spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags);
711
712 return 0;
713}
714
715
716static void qib_unregister_observers(struct qib_devdata *dd)
717{
718 struct diag_observer_list_elt *olp;
719 unsigned long flags;
720
721 spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
722 olp = dd->diag_observer_list;
723 while (olp) {
724
725 dd->diag_observer_list = olp->next;
726 spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags);
727 vfree(olp);
728
729 spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
730 olp = dd->diag_observer_list;
731 }
732 spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags);
733}
734
735
736
737
738
739
740static const struct diag_observer *diag_get_observer(struct qib_devdata *dd,
741 u32 addr)
742{
743 struct diag_observer_list_elt *olp;
744 const struct diag_observer *op = NULL;
745
746 olp = dd->diag_observer_list;
747 while (olp) {
748 op = olp->op;
749 if (addr >= op->bottom && addr <= op->top)
750 break;
751 olp = olp->next;
752 }
753 if (!olp)
754 op = NULL;
755
756 return op;
757}
758
759static ssize_t qib_diag_read(struct file *fp, char __user *data,
760 size_t count, loff_t *off)
761{
762 struct qib_diag_client *dc = fp->private_data;
763 struct qib_devdata *dd = dc->dd;
764 ssize_t ret;
765
766 if (dc->pid != current->pid) {
767 ret = -EPERM;
768 goto bail;
769 }
770
771 if (count == 0)
772 ret = 0;
773 else if ((count % 4) || (*off % 4))
774
775 ret = -EINVAL;
776 else if (dc->state < READY && (*off || count != 8))
777 ret = -EINVAL;
778 else {
779 unsigned long flags;
780 u64 data64 = 0;
781 int use_32;
782 const struct diag_observer *op;
783
784 use_32 = (count % 8) || (*off % 8);
785 ret = -1;
786 spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
787
788
789
790
791
792 op = diag_get_observer(dd, *off);
793 if (op) {
794 u32 offset = *off;
795
796 ret = op->hook(dd, op, offset, &data64, 0, use_32);
797 }
798
799
800
801
802 spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags);
803 if (!op) {
804 if (use_32)
805
806
807
808
809 ret = qib_read_umem32(dd, data, (u32) *off,
810 count);
811 else
812 ret = qib_read_umem64(dd, data, (u32) *off,
813 count);
814 } else if (ret == count) {
815
816 ret = copy_to_user(data, &data64, use_32 ?
817 sizeof(u32) : sizeof(u64));
818 if (ret)
819 ret = -EFAULT;
820 }
821 }
822
823 if (ret >= 0) {
824 *off += count;
825 ret = count;
826 if (dc->state == OPENED)
827 dc->state = INIT;
828 }
829bail:
830 return ret;
831}
832
833static ssize_t qib_diag_write(struct file *fp, const char __user *data,
834 size_t count, loff_t *off)
835{
836 struct qib_diag_client *dc = fp->private_data;
837 struct qib_devdata *dd = dc->dd;
838 ssize_t ret;
839
840 if (dc->pid != current->pid) {
841 ret = -EPERM;
842 goto bail;
843 }
844
845 if (count == 0)
846 ret = 0;
847 else if ((count % 4) || (*off % 4))
848
849 ret = -EINVAL;
850 else if (dc->state < READY &&
851 ((*off || count != 8) || dc->state != INIT))
852
853 ret = -EINVAL;
854 else {
855 unsigned long flags;
856 const struct diag_observer *op = NULL;
857 int use_32 = (count % 8) || (*off % 8);
858
859
860
861
862
863
864
865
866
867 if (count == 4 || count == 8) {
868 u64 data64;
869 u32 offset = *off;
870
871 ret = copy_from_user(&data64, data, count);
872 if (ret) {
873 ret = -EFAULT;
874 goto bail;
875 }
876 spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
877 op = diag_get_observer(dd, *off);
878 if (op)
879 ret = op->hook(dd, op, offset, &data64, ~0Ull,
880 use_32);
881 spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags);
882 }
883
884 if (!op) {
885 if (use_32)
886
887
888
889
890 ret = qib_write_umem32(dd, (u32) *off, data,
891 count);
892 else
893 ret = qib_write_umem64(dd, (u32) *off, data,
894 count);
895 }
896 }
897
898 if (ret >= 0) {
899 *off += count;
900 ret = count;
901 if (dc->state == INIT)
902 dc->state = READY;
903 }
904bail:
905 return ret;
906}
907