diff options
author | Roland Dreier <roland@purestorage.com> | 2011-05-20 14:46:11 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-05-20 14:46:11 -0400 |
commit | b2cbae2c248776d81cc265ff7d48405b6a4cc463 (patch) | |
tree | fbd4f4e0812fbcc991670c81967e90bfdd9f80c0 /drivers/infiniband | |
parent | fd75c789abf7948e16fe50917a6acb809927719a (diff) |
RDMA: Add netlink infrastructure
Add basic RDMA netlink infrastructure that allows for registration of
RDMA clients for which data is to be exported and supplies message
construction callbacks.
Signed-off-by: Nir Muchtar <nirm@voltaire.com>
[ Reorganize a few things, add CONFIG_NET dependency. - Roland ]
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/Kconfig | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/infiniband/core/device.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/core/netlink.c | 190 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/Kconfig | 2 |
5 files changed, 205 insertions, 3 deletions
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index 6e35eccc9caa..0f9a84c1046a 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig | |||
@@ -2,6 +2,7 @@ menuconfig INFINIBAND | |||
2 | tristate "InfiniBand support" | 2 | tristate "InfiniBand support" |
3 | depends on PCI || BROKEN | 3 | depends on PCI || BROKEN |
4 | depends on HAS_IOMEM | 4 | depends on HAS_IOMEM |
5 | depends on NET | ||
5 | ---help--- | 6 | ---help--- |
6 | Core support for InfiniBand (IB). Make sure to also select | 7 | Core support for InfiniBand (IB). Make sure to also select |
7 | any protocols you wish to use as well as drivers for your | 8 | any protocols you wish to use as well as drivers for your |
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile index cb1ab3ea4998..c8bbaef1becb 100644 --- a/drivers/infiniband/core/Makefile +++ b/drivers/infiniband/core/Makefile | |||
@@ -8,7 +8,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ | |||
8 | $(user_access-y) | 8 | $(user_access-y) |
9 | 9 | ||
10 | ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ | 10 | ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ |
11 | device.o fmr_pool.o cache.o | 11 | device.o fmr_pool.o cache.o netlink.o |
12 | ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o | 12 | ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o |
13 | 13 | ||
14 | ib_mad-y := mad.o smi.o agent.o mad_rmpp.o | 14 | ib_mad-y := mad.o smi.o agent.o mad_rmpp.o |
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 46a7a3febc12..4007f721d25d 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
41 | #include <rdma/rdma_netlink.h> | ||
41 | 42 | ||
42 | #include "core_priv.h" | 43 | #include "core_priv.h" |
43 | 44 | ||
@@ -730,14 +731,23 @@ static int __init ib_core_init(void) | |||
730 | goto err; | 731 | goto err; |
731 | } | 732 | } |
732 | 733 | ||
734 | ret = ibnl_init(); | ||
735 | if (ret) { | ||
736 | printk(KERN_WARNING "Couldn't init IB netlink interface\n"); | ||
737 | goto err_sysfs; | ||
738 | } | ||
739 | |||
733 | ret = ib_cache_setup(); | 740 | ret = ib_cache_setup(); |
734 | if (ret) { | 741 | if (ret) { |
735 | printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); | 742 | printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); |
736 | goto err_sysfs; | 743 | goto err_nl; |
737 | } | 744 | } |
738 | 745 | ||
739 | return 0; | 746 | return 0; |
740 | 747 | ||
748 | err_nl: | ||
749 | ibnl_cleanup(); | ||
750 | |||
741 | err_sysfs: | 751 | err_sysfs: |
742 | ib_sysfs_cleanup(); | 752 | ib_sysfs_cleanup(); |
743 | 753 | ||
@@ -749,6 +759,7 @@ err: | |||
749 | static void __exit ib_core_cleanup(void) | 759 | static void __exit ib_core_cleanup(void) |
750 | { | 760 | { |
751 | ib_cache_cleanup(); | 761 | ib_cache_cleanup(); |
762 | ibnl_cleanup(); | ||
752 | ib_sysfs_cleanup(); | 763 | ib_sysfs_cleanup(); |
753 | /* Make sure that any pending umem accounting work is done. */ | 764 | /* Make sure that any pending umem accounting work is done. */ |
754 | destroy_workqueue(ib_wq); | 765 | destroy_workqueue(ib_wq); |
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c new file mode 100644 index 000000000000..4a5abaf0a25c --- /dev/null +++ b/drivers/infiniband/core/netlink.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Voltaire Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ | ||
34 | |||
35 | #include <net/netlink.h> | ||
36 | #include <net/net_namespace.h> | ||
37 | #include <net/sock.h> | ||
38 | #include <rdma/rdma_netlink.h> | ||
39 | |||
40 | struct ibnl_client { | ||
41 | struct list_head list; | ||
42 | int index; | ||
43 | int nops; | ||
44 | const struct ibnl_client_cbs *cb_table; | ||
45 | }; | ||
46 | |||
47 | static DEFINE_MUTEX(ibnl_mutex); | ||
48 | static struct sock *nls; | ||
49 | static LIST_HEAD(client_list); | ||
50 | |||
51 | int ibnl_add_client(int index, int nops, | ||
52 | const struct ibnl_client_cbs cb_table[]) | ||
53 | { | ||
54 | struct ibnl_client *cur; | ||
55 | struct ibnl_client *nl_client; | ||
56 | |||
57 | nl_client = kmalloc(sizeof *nl_client, GFP_KERNEL); | ||
58 | if (!nl_client) | ||
59 | return -ENOMEM; | ||
60 | |||
61 | nl_client->index = index; | ||
62 | nl_client->nops = nops; | ||
63 | nl_client->cb_table = cb_table; | ||
64 | |||
65 | mutex_lock(&ibnl_mutex); | ||
66 | |||
67 | list_for_each_entry(cur, &client_list, list) { | ||
68 | if (cur->index == index) { | ||
69 | pr_warn("Client for %d already exists\n", index); | ||
70 | mutex_unlock(&ibnl_mutex); | ||
71 | kfree(nl_client); | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | list_add_tail(&nl_client->list, &client_list); | ||
77 | |||
78 | mutex_unlock(&ibnl_mutex); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | EXPORT_SYMBOL(ibnl_add_client); | ||
83 | |||
84 | int ibnl_remove_client(int index) | ||
85 | { | ||
86 | struct ibnl_client *cur, *next; | ||
87 | |||
88 | mutex_lock(&ibnl_mutex); | ||
89 | list_for_each_entry_safe(cur, next, &client_list, list) { | ||
90 | if (cur->index == index) { | ||
91 | list_del(&(cur->list)); | ||
92 | mutex_unlock(&ibnl_mutex); | ||
93 | kfree(cur); | ||
94 | return 0; | ||
95 | } | ||
96 | } | ||
97 | pr_warn("Can't remove callback for client idx %d. Not found\n", index); | ||
98 | mutex_unlock(&ibnl_mutex); | ||
99 | |||
100 | return -EINVAL; | ||
101 | } | ||
102 | EXPORT_SYMBOL(ibnl_remove_client); | ||
103 | |||
104 | void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq, | ||
105 | int len, int client, int op) | ||
106 | { | ||
107 | unsigned char *prev_tail; | ||
108 | |||
109 | prev_tail = skb_tail_pointer(skb); | ||
110 | *nlh = NLMSG_NEW(skb, 0, seq, RDMA_NL_GET_TYPE(client, op), | ||
111 | len, NLM_F_MULTI); | ||
112 | (*nlh)->nlmsg_len = skb_tail_pointer(skb) - prev_tail; | ||
113 | return NLMSG_DATA(*nlh); | ||
114 | |||
115 | nlmsg_failure: | ||
116 | nlmsg_trim(skb, prev_tail); | ||
117 | return NULL; | ||
118 | } | ||
119 | EXPORT_SYMBOL(ibnl_put_msg); | ||
120 | |||
121 | int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
122 | int len, void *data, int type) | ||
123 | { | ||
124 | unsigned char *prev_tail; | ||
125 | |||
126 | prev_tail = skb_tail_pointer(skb); | ||
127 | NLA_PUT(skb, type, len, data); | ||
128 | nlh->nlmsg_len += skb_tail_pointer(skb) - prev_tail; | ||
129 | return 0; | ||
130 | |||
131 | nla_put_failure: | ||
132 | nlmsg_trim(skb, prev_tail - nlh->nlmsg_len); | ||
133 | return -EMSGSIZE; | ||
134 | } | ||
135 | EXPORT_SYMBOL(ibnl_put_attr); | ||
136 | |||
137 | static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
138 | { | ||
139 | struct ibnl_client *client; | ||
140 | int type = nlh->nlmsg_type; | ||
141 | int index = RDMA_NL_GET_CLIENT(type); | ||
142 | int op = RDMA_NL_GET_OP(type); | ||
143 | |||
144 | list_for_each_entry(client, &client_list, list) { | ||
145 | if (client->index == index) { | ||
146 | if (op < 0 || op >= client->nops || | ||
147 | !client->cb_table[RDMA_NL_GET_OP(op)].dump) | ||
148 | return -EINVAL; | ||
149 | return netlink_dump_start(nls, skb, nlh, | ||
150 | client->cb_table[op].dump, | ||
151 | NULL); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | pr_info("Index %d wasn't found in client list\n", index); | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | static void ibnl_rcv(struct sk_buff *skb) | ||
160 | { | ||
161 | mutex_lock(&ibnl_mutex); | ||
162 | netlink_rcv_skb(skb, &ibnl_rcv_msg); | ||
163 | mutex_unlock(&ibnl_mutex); | ||
164 | } | ||
165 | |||
166 | int __init ibnl_init(void) | ||
167 | { | ||
168 | nls = netlink_kernel_create(&init_net, NETLINK_RDMA, 0, ibnl_rcv, | ||
169 | NULL, THIS_MODULE); | ||
170 | if (!nls) { | ||
171 | pr_warn("Failed to create netlink socket\n"); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | void ibnl_cleanup(void) | ||
179 | { | ||
180 | struct ibnl_client *cur, *next; | ||
181 | |||
182 | mutex_lock(&ibnl_mutex); | ||
183 | list_for_each_entry_safe(cur, next, &client_list, list) { | ||
184 | list_del(&(cur->list)); | ||
185 | kfree(cur); | ||
186 | } | ||
187 | mutex_unlock(&ibnl_mutex); | ||
188 | |||
189 | netlink_kernel_release(nls); | ||
190 | } | ||
diff --git a/drivers/infiniband/hw/qib/Kconfig b/drivers/infiniband/hw/qib/Kconfig index 7c03a70c55a2..8349f9c5064c 100644 --- a/drivers/infiniband/hw/qib/Kconfig +++ b/drivers/infiniband/hw/qib/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config INFINIBAND_QIB | 1 | config INFINIBAND_QIB |
2 | tristate "QLogic PCIe HCA support" | 2 | tristate "QLogic PCIe HCA support" |
3 | depends on 64BIT && NET | 3 | depends on 64BIT |
4 | ---help--- | 4 | ---help--- |
5 | This is a low-level driver for QLogic PCIe QLE InfiniBand host | 5 | This is a low-level driver for QLogic PCIe QLE InfiniBand host |
6 | channel adapters. This driver does not support the QLogic | 6 | channel adapters. This driver does not support the QLogic |