diff options
author | Dennis Dalessandro <dennis.dalessandro@intel.com> | 2016-05-19 08:25:50 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-05-26 11:23:17 -0400 |
commit | 0eb626590dcf1280c6d01a784e9d53a3de6d5e8e (patch) | |
tree | fa8a4b60c2b69da52801b79fa61add9f75da7075 | |
parent | f3225c3f1107104f5e143797550476182b844cfb (diff) |
IB/hfi1: Remove multiple device cdev
hfi1 current exports a cdev that can be used to target all of the hfi's
in the system. However there is a problem with this approach in
that the devices could be on different subnets. This is a problem that
user space can figure out and explicitly tell the driver on which device
to create a context.
Remove the multi-purpose cdev leaving a dedicated cdev for each port.
Also remove the striping capability that is dependent upon the user
choosing the multi-purpose cdev. It is now up to user space to determine
how to stripe contexts.
Reviewed-by: Dean Luick <dean.luick@intel.com>
Reviewed-by: Mitko Haralanov <mitko.haralanov@intel.com>
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/staging/rdma/hfi1/file_ops.c | 102 | ||||
-rw-r--r-- | include/uapi/rdma/hfi/hfi1_user.h | 19 |
2 files changed, 21 insertions, 100 deletions
diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c index c1c5bf82addb..518cd891b63d 100644 --- a/drivers/staging/rdma/hfi1/file_ops.c +++ b/drivers/staging/rdma/hfi1/file_ops.c | |||
@@ -86,8 +86,7 @@ static int get_ctxt_info(struct file *, void __user *, __u32); | |||
86 | static int get_base_info(struct file *, void __user *, __u32); | 86 | static int get_base_info(struct file *, void __user *, __u32); |
87 | static int setup_ctxt(struct file *); | 87 | static int setup_ctxt(struct file *); |
88 | static int setup_subctxt(struct hfi1_ctxtdata *); | 88 | static int setup_subctxt(struct hfi1_ctxtdata *); |
89 | static int get_user_context(struct file *, struct hfi1_user_info *, | 89 | static int get_user_context(struct file *, struct hfi1_user_info *, int); |
90 | int, unsigned); | ||
91 | static int find_shared_ctxt(struct file *, const struct hfi1_user_info *); | 90 | static int find_shared_ctxt(struct file *, const struct hfi1_user_info *); |
92 | static int allocate_ctxt(struct file *, struct hfi1_devdata *, | 91 | static int allocate_ctxt(struct file *, struct hfi1_devdata *, |
93 | struct hfi1_user_info *); | 92 | struct hfi1_user_info *); |
@@ -836,7 +835,7 @@ static u64 kvirt_to_phys(void *addr) | |||
836 | static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo) | 835 | static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo) |
837 | { | 836 | { |
838 | int i_minor, ret = 0; | 837 | int i_minor, ret = 0; |
839 | unsigned swmajor, swminor, alg = HFI1_ALG_ACROSS; | 838 | unsigned int swmajor, swminor; |
840 | 839 | ||
841 | swmajor = uinfo->userversion >> 16; | 840 | swmajor = uinfo->userversion >> 16; |
842 | if (swmajor != HFI1_USER_SWMAJOR) { | 841 | if (swmajor != HFI1_USER_SWMAJOR) { |
@@ -846,9 +845,6 @@ static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo) | |||
846 | 845 | ||
847 | swminor = uinfo->userversion & 0xffff; | 846 | swminor = uinfo->userversion & 0xffff; |
848 | 847 | ||
849 | if (uinfo->hfi1_alg < HFI1_ALG_COUNT) | ||
850 | alg = uinfo->hfi1_alg; | ||
851 | |||
852 | mutex_lock(&hfi1_mutex); | 848 | mutex_lock(&hfi1_mutex); |
853 | /* First, lets check if we need to setup a shared context? */ | 849 | /* First, lets check if we need to setup a shared context? */ |
854 | if (uinfo->subctxt_cnt) { | 850 | if (uinfo->subctxt_cnt) { |
@@ -868,7 +864,7 @@ static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo) | |||
868 | */ | 864 | */ |
869 | if (!ret) { | 865 | if (!ret) { |
870 | i_minor = iminor(file_inode(fp)) - HFI1_USER_MINOR_BASE; | 866 | i_minor = iminor(file_inode(fp)) - HFI1_USER_MINOR_BASE; |
871 | ret = get_user_context(fp, uinfo, i_minor - 1, alg); | 867 | ret = get_user_context(fp, uinfo, i_minor); |
872 | } | 868 | } |
873 | done_unlock: | 869 | done_unlock: |
874 | mutex_unlock(&hfi1_mutex); | 870 | mutex_unlock(&hfi1_mutex); |
@@ -876,71 +872,26 @@ done: | |||
876 | return ret; | 872 | return ret; |
877 | } | 873 | } |
878 | 874 | ||
879 | /* return true if the device available for general use */ | ||
880 | static int usable_device(struct hfi1_devdata *dd) | ||
881 | { | ||
882 | struct hfi1_pportdata *ppd = dd->pport; | ||
883 | |||
884 | return driver_lstate(ppd) == IB_PORT_ACTIVE; | ||
885 | } | ||
886 | |||
887 | static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo, | 875 | static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo, |
888 | int devno, unsigned alg) | 876 | int devno) |
889 | { | 877 | { |
890 | struct hfi1_devdata *dd = NULL; | 878 | struct hfi1_devdata *dd = NULL; |
891 | int ret = 0, devmax, npresent, nup, dev; | 879 | int devmax, npresent, nup; |
892 | 880 | ||
893 | devmax = hfi1_count_units(&npresent, &nup); | 881 | devmax = hfi1_count_units(&npresent, &nup); |
894 | if (!npresent) { | 882 | if (!npresent) |
895 | ret = -ENXIO; | 883 | return -ENXIO; |
896 | goto done; | 884 | |
897 | } | 885 | if (!nup) |
898 | if (!nup) { | 886 | return -ENETDOWN; |
899 | ret = -ENETDOWN; | 887 | |
900 | goto done; | 888 | dd = hfi1_lookup(devno); |
901 | } | 889 | if (!dd) |
902 | if (devno >= 0) { | 890 | return -ENODEV; |
903 | dd = hfi1_lookup(devno); | 891 | else if (!dd->freectxts) |
904 | if (!dd) | 892 | return -EBUSY; |
905 | ret = -ENODEV; | 893 | |
906 | else if (!dd->freectxts) | 894 | return allocate_ctxt(fp, dd, uinfo); |
907 | ret = -EBUSY; | ||
908 | } else { | ||
909 | struct hfi1_devdata *pdd; | ||
910 | |||
911 | if (alg == HFI1_ALG_ACROSS) { | ||
912 | unsigned free = 0U; | ||
913 | |||
914 | for (dev = 0; dev < devmax; dev++) { | ||
915 | pdd = hfi1_lookup(dev); | ||
916 | if (!pdd) | ||
917 | continue; | ||
918 | if (!usable_device(pdd)) | ||
919 | continue; | ||
920 | if (pdd->freectxts && | ||
921 | pdd->freectxts > free) { | ||
922 | dd = pdd; | ||
923 | free = pdd->freectxts; | ||
924 | } | ||
925 | } | ||
926 | } else { | ||
927 | for (dev = 0; dev < devmax; dev++) { | ||
928 | pdd = hfi1_lookup(dev); | ||
929 | if (!pdd) | ||
930 | continue; | ||
931 | if (!usable_device(pdd)) | ||
932 | continue; | ||
933 | if (pdd->freectxts) { | ||
934 | dd = pdd; | ||
935 | break; | ||
936 | } | ||
937 | } | ||
938 | } | ||
939 | if (!dd) | ||
940 | ret = -EBUSY; | ||
941 | } | ||
942 | done: | ||
943 | return ret ? ret : allocate_ctxt(fp, dd, uinfo); | ||
944 | } | 895 | } |
945 | 896 | ||
946 | static int find_shared_ctxt(struct file *fp, | 897 | static int find_shared_ctxt(struct file *fp, |
@@ -1698,15 +1649,8 @@ static const struct file_operations ui_file_ops = { | |||
1698 | #define UI_OFFSET 192 /* device minor offset for UI devices */ | 1649 | #define UI_OFFSET 192 /* device minor offset for UI devices */ |
1699 | static int create_ui = 1; | 1650 | static int create_ui = 1; |
1700 | 1651 | ||
1701 | static struct cdev wildcard_cdev; | ||
1702 | static struct device *wildcard_device; | ||
1703 | |||
1704 | static atomic_t user_count = ATOMIC_INIT(0); | ||
1705 | |||
1706 | static void user_remove(struct hfi1_devdata *dd) | 1652 | static void user_remove(struct hfi1_devdata *dd) |
1707 | { | 1653 | { |
1708 | if (atomic_dec_return(&user_count) == 0) | ||
1709 | hfi1_cdev_cleanup(&wildcard_cdev, &wildcard_device); | ||
1710 | 1654 | ||
1711 | hfi1_cdev_cleanup(&dd->user_cdev, &dd->user_device); | 1655 | hfi1_cdev_cleanup(&dd->user_cdev, &dd->user_device); |
1712 | hfi1_cdev_cleanup(&dd->ui_cdev, &dd->ui_device); | 1656 | hfi1_cdev_cleanup(&dd->ui_cdev, &dd->ui_device); |
@@ -1717,16 +1661,8 @@ static int user_add(struct hfi1_devdata *dd) | |||
1717 | char name[10]; | 1661 | char name[10]; |
1718 | int ret; | 1662 | int ret; |
1719 | 1663 | ||
1720 | if (atomic_inc_return(&user_count) == 1) { | ||
1721 | ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops, | ||
1722 | &wildcard_cdev, &wildcard_device, | ||
1723 | true); | ||
1724 | if (ret) | ||
1725 | goto done; | ||
1726 | } | ||
1727 | |||
1728 | snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit); | 1664 | snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit); |
1729 | ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops, | 1665 | ret = hfi1_cdev_init(dd->unit, name, &hfi1_file_ops, |
1730 | &dd->user_cdev, &dd->user_device, | 1666 | &dd->user_cdev, &dd->user_device, |
1731 | true); | 1667 | true); |
1732 | if (ret) | 1668 | if (ret) |
diff --git a/include/uapi/rdma/hfi/hfi1_user.h b/include/uapi/rdma/hfi/hfi1_user.h index a533cecab14f..09558999ca1d 100644 --- a/include/uapi/rdma/hfi/hfi1_user.h +++ b/include/uapi/rdma/hfi/hfi1_user.h | |||
@@ -75,7 +75,7 @@ | |||
75 | * may not be implemented; the user code must deal with this if it | 75 | * may not be implemented; the user code must deal with this if it |
76 | * cares, or it must abort after initialization reports the difference. | 76 | * cares, or it must abort after initialization reports the difference. |
77 | */ | 77 | */ |
78 | #define HFI1_USER_SWMINOR 0 | 78 | #define HFI1_USER_SWMINOR 1 |
79 | 79 | ||
80 | /* | 80 | /* |
81 | * Set of HW and driver capability/feature bits. | 81 | * Set of HW and driver capability/feature bits. |
@@ -107,19 +107,6 @@ | |||
107 | #define HFI1_RCVHDR_ENTSIZE_16 (1UL << 1) | 107 | #define HFI1_RCVHDR_ENTSIZE_16 (1UL << 1) |
108 | #define HFI1_RCVDHR_ENTSIZE_32 (1UL << 2) | 108 | #define HFI1_RCVDHR_ENTSIZE_32 (1UL << 2) |
109 | 109 | ||
110 | /* | ||
111 | * If the unit is specified via open, HFI choice is fixed. If port is | ||
112 | * specified, it's also fixed. Otherwise we try to spread contexts | ||
113 | * across ports and HFIs, using different algorithms. WITHIN is | ||
114 | * the old default, prior to this mechanism. | ||
115 | */ | ||
116 | #define HFI1_ALG_ACROSS 0 /* round robin contexts across HFIs, then | ||
117 | * ports; this is the default */ | ||
118 | #define HFI1_ALG_WITHIN 1 /* use all contexts on an HFI (round robin | ||
119 | * active ports within), then next HFI */ | ||
120 | #define HFI1_ALG_COUNT 2 /* number of algorithm choices */ | ||
121 | |||
122 | |||
123 | /* User commands. */ | 110 | /* User commands. */ |
124 | #define HFI1_CMD_ASSIGN_CTXT 1 /* allocate HFI and context */ | 111 | #define HFI1_CMD_ASSIGN_CTXT 1 /* allocate HFI and context */ |
125 | #define HFI1_CMD_CTXT_INFO 2 /* find out what resources we got */ | 112 | #define HFI1_CMD_CTXT_INFO 2 /* find out what resources we got */ |
@@ -199,9 +186,7 @@ struct hfi1_user_info { | |||
199 | * Should be set to HFI1_USER_SWVERSION. | 186 | * Should be set to HFI1_USER_SWVERSION. |
200 | */ | 187 | */ |
201 | __u32 userversion; | 188 | __u32 userversion; |
202 | __u16 pad; | 189 | __u32 pad; |
203 | /* HFI selection algorithm, if unit has not selected */ | ||
204 | __u16 hfi1_alg; | ||
205 | /* | 190 | /* |
206 | * If two or more processes wish to share a context, each process | 191 | * If two or more processes wish to share a context, each process |
207 | * must set the subcontext_cnt and subcontext_id to the same | 192 | * must set the subcontext_cnt and subcontext_id to the same |