aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/uverbs_main.c')
-rw-r--r--drivers/infiniband/core/uverbs_main.c127
1 files changed, 98 insertions, 29 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 2df31f68ea09..189d99e76d9f 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -115,11 +115,16 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
115 [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd, 115 [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
116 [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq, 116 [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
117 [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp, 117 [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp,
118};
119
118#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING 120#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
119 [IB_USER_VERBS_CMD_CREATE_FLOW] = ib_uverbs_create_flow, 121static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
120 [IB_USER_VERBS_CMD_DESTROY_FLOW] = ib_uverbs_destroy_flow 122 struct ib_udata *ucore,
121#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */ 123 struct ib_udata *uhw) = {
124 [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
125 [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow
122}; 126};
127#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
123 128
124static void ib_uverbs_add_one(struct ib_device *device); 129static void ib_uverbs_add_one(struct ib_device *device);
125static void ib_uverbs_remove_one(struct ib_device *device); 130static void ib_uverbs_remove_one(struct ib_device *device);
@@ -589,6 +594,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
589{ 594{
590 struct ib_uverbs_file *file = filp->private_data; 595 struct ib_uverbs_file *file = filp->private_data;
591 struct ib_uverbs_cmd_hdr hdr; 596 struct ib_uverbs_cmd_hdr hdr;
597 __u32 flags;
592 598
593 if (count < sizeof hdr) 599 if (count < sizeof hdr)
594 return -EINVAL; 600 return -EINVAL;
@@ -596,45 +602,108 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
596 if (copy_from_user(&hdr, buf, sizeof hdr)) 602 if (copy_from_user(&hdr, buf, sizeof hdr))
597 return -EFAULT; 603 return -EFAULT;
598 604
599 if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || 605 flags = (hdr.command &
600 !uverbs_cmd_table[hdr.command]) 606 IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
601 return -EINVAL;
602 607
603 if (!file->ucontext && 608 if (!flags) {
604 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT) 609 __u32 command;
605 return -EINVAL;
606 610
607 if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command))) 611 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
608 return -ENOSYS; 612 IB_USER_VERBS_CMD_COMMAND_MASK))
613 return -EINVAL;
609 614
610#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING 615 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
611 if (hdr.command >= IB_USER_VERBS_CMD_THRESHOLD) {
612 struct ib_uverbs_cmd_hdr_ex hdr_ex;
613 616
614 if (copy_from_user(&hdr_ex, buf, sizeof(hdr_ex))) 617 if (command >= ARRAY_SIZE(uverbs_cmd_table) ||
615 return -EFAULT; 618 !uverbs_cmd_table[command])
619 return -EINVAL;
616 620
617 if (((hdr_ex.in_words + hdr_ex.provider_in_words) * 4) != count) 621 if (!file->ucontext &&
622 command != IB_USER_VERBS_CMD_GET_CONTEXT)
618 return -EINVAL; 623 return -EINVAL;
619 624
620 return uverbs_cmd_table[hdr.command](file, 625 if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << command)))
621 buf + sizeof(hdr_ex), 626 return -ENOSYS;
622 (hdr_ex.in_words + 627
623 hdr_ex.provider_in_words) * 4,
624 (hdr_ex.out_words +
625 hdr_ex.provider_out_words) * 4);
626 } else {
627#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
628 if (hdr.in_words * 4 != count) 628 if (hdr.in_words * 4 != count)
629 return -EINVAL; 629 return -EINVAL;
630 630
631 return uverbs_cmd_table[hdr.command](file, 631 return uverbs_cmd_table[command](file,
632 buf + sizeof(hdr), 632 buf + sizeof(hdr),
633 hdr.in_words * 4, 633 hdr.in_words * 4,
634 hdr.out_words * 4); 634 hdr.out_words * 4);
635
635#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING 636#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
637
638 } else if (flags == IB_USER_VERBS_CMD_FLAG_EXTENDED) {
639 __u32 command;
640
641 struct ib_uverbs_ex_cmd_hdr ex_hdr;
642 struct ib_udata ucore;
643 struct ib_udata uhw;
644 int err;
645 size_t written_count = count;
646
647 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
648 IB_USER_VERBS_CMD_COMMAND_MASK))
649 return -EINVAL;
650
651 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
652
653 if (command >= ARRAY_SIZE(uverbs_ex_cmd_table) ||
654 !uverbs_ex_cmd_table[command])
655 return -ENOSYS;
656
657 if (!file->ucontext)
658 return -EINVAL;
659
660 if (!(file->device->ib_dev->uverbs_ex_cmd_mask & (1ull << command)))
661 return -ENOSYS;
662
663 if (count < (sizeof(hdr) + sizeof(ex_hdr)))
664 return -EINVAL;
665
666 if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr)))
667 return -EFAULT;
668
669 count -= sizeof(hdr) + sizeof(ex_hdr);
670 buf += sizeof(hdr) + sizeof(ex_hdr);
671
672 if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
673 return -EINVAL;
674
675 if (ex_hdr.response) {
676 if (!hdr.out_words && !ex_hdr.provider_out_words)
677 return -EINVAL;
678 } else {
679 if (hdr.out_words || ex_hdr.provider_out_words)
680 return -EINVAL;
681 }
682
683 INIT_UDATA(&ucore,
684 (hdr.in_words) ? buf : 0,
685 (unsigned long)ex_hdr.response,
686 hdr.in_words * 8,
687 hdr.out_words * 8);
688
689 INIT_UDATA(&uhw,
690 (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
691 (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
692 ex_hdr.provider_in_words * 8,
693 ex_hdr.provider_out_words * 8);
694
695 err = uverbs_ex_cmd_table[command](file,
696 &ucore,
697 &uhw);
698
699 if (err)
700 return err;
701
702 return written_count;
636 } 703 }
637#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */ 704#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
705
706 return -ENOSYS;
638} 707}
639 708
640static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) 709static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)