ib/cm: separate listen callback into own handler
[mirror/winof/.git] / core / al / kernel / al_cm.c
1 /*\r
2  * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  */\r
29 \r
30 #include <iba/ib_cm_ifc.h>\r
31 #include "al_cm_cep.h"\r
32 #include "al_mgr.h"\r
33 #include "al_proxy.h"\r
34 #include "al_cm_conn.h"\r
35 #include "al_cm_sidr.h"\r
36 \r
37 typedef struct _iba_cm_id_priv\r
38 {\r
39         iba_cm_id       id;\r
40         KEVENT          destroy_event;\r
41 \r
42 }       iba_cm_id_priv;\r
43 \r
44 static iba_cm_id*\r
45 cm_alloc_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
46                         void *context)\r
47 {\r
48         iba_cm_id_priv  *id;\r
49 \r
50         id = ExAllocatePoolWithTag(NonPagedPool, sizeof(iba_cm_id_priv), 'mcbi');\r
51         if (id == NULL) {\r
52                 return NULL;\r
53         }\r
54 \r
55         KeInitializeEvent(&id->destroy_event, NotificationEvent, FALSE);\r
56         id->id.callback = callback;\r
57         id->id.context = context;\r
58         return &id->id;\r
59 }\r
60 \r
61 static void\r
62 cm_free_id(iba_cm_id *id)\r
63 {\r
64         ExFreePool(CONTAINING_RECORD(id, iba_cm_id_priv, id));\r
65 }\r
66 \r
67 static void\r
68 cm_destroy_handler(void *context)\r
69 {\r
70         iba_cm_id_priv  *id = context;\r
71         KeSetEvent(&id->destroy_event, 0, FALSE);\r
72 }\r
73 \r
74 static void\r
75 cm_cep_handler(const ib_al_handle_t h_al, const net32_t cid)\r
76 {\r
77         void                            *context;\r
78         net32_t                         new_cid;\r
79         ib_mad_element_t        *mad;\r
80         iba_cm_id                       *id;\r
81         iba_cm_event            event;\r
82         NTSTATUS                        status;\r
83 \r
84         while (al_cep_poll(h_al, cid, &context, &new_cid, &mad) == IB_SUCCESS) {\r
85 \r
86                 id = (iba_cm_id *) context;\r
87                 kal_cep_format_event(h_al, id->cid, mad, &event);\r
88 \r
89                 status = id->callback(id, &event);\r
90                 if (!NT_SUCCESS(status)) {\r
91                         kal_cep_config(h_al, new_cid, NULL, NULL, NULL);\r
92                         kal_cep_destroy(h_al, id->cid, status);\r
93                         cm_free_id(id);\r
94                 }\r
95                 ib_put_mad(mad);\r
96         }\r
97 }\r
98 \r
99 static void\r
100 cm_listen_handler(const ib_al_handle_t h_al, const net32_t cid)\r
101 {\r
102         void                            *context;\r
103         net32_t                         new_cid;\r
104         ib_mad_element_t        *mad;\r
105         iba_cm_id                       *id, *listen_id;\r
106         iba_cm_event            event;\r
107         NTSTATUS                        status;\r
108 \r
109         while (al_cep_poll(h_al, cid, &context, &new_cid, &mad) == IB_SUCCESS) {\r
110 \r
111                 listen_id = (iba_cm_id *) context;\r
112 \r
113                 id = cm_alloc_id(listen_id->callback, listen_id);\r
114                 if (id == NULL) {\r
115                         kal_cep_destroy(h_al, new_cid, STATUS_NO_MORE_ENTRIES);\r
116                         ib_put_mad(mad);\r
117                         continue;\r
118                 }\r
119 \r
120                 kal_cep_config(h_al, new_cid, cm_cep_handler, id, cm_destroy_handler);\r
121                 id->cid = new_cid;\r
122 \r
123                 kal_cep_format_event(h_al, id->cid, mad, &event);\r
124                 status = id->callback(id, &event);\r
125                 if (!NT_SUCCESS(status)) {\r
126                         kal_cep_config(h_al, new_cid, NULL, NULL, NULL);\r
127                         kal_cep_destroy(h_al, id->cid, status);\r
128                         cm_free_id(id);\r
129                 }\r
130                 ib_put_mad(mad);\r
131         }\r
132 }\r
133 \r
134 static NTSTATUS\r
135 cm_create_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
136                          void *context, iba_cm_id **pp_id)\r
137 {\r
138         iba_cm_id               *id;\r
139         ib_api_status_t ib_status;\r
140 \r
141         id = cm_alloc_id(callback, context);\r
142         if (id == NULL) {\r
143                 return STATUS_NO_MEMORY;\r
144         }\r
145 \r
146         ib_status = kal_cep_alloc(gh_al, &id->cid);\r
147         if (ib_status != IB_SUCCESS) {\r
148                 cm_free_id(id);\r
149                 return ib_to_ntstatus(ib_status);\r
150         }\r
151 \r
152         kal_cep_config(gh_al, id->cid, cm_cep_handler, id, cm_destroy_handler);\r
153         *pp_id = id;\r
154         return STATUS_SUCCESS;\r
155 }\r
156 \r
157 static void\r
158 cm_destroy_id(iba_cm_id *p_id)\r
159 {\r
160         iba_cm_id_priv  *id;\r
161 \r
162         id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);\r
163         kal_cep_destroy(gh_al, p_id->cid, STATUS_SUCCESS);\r
164         KeWaitForSingleObject(&id->destroy_event, Executive, KernelMode, FALSE, NULL);\r
165         cm_free_id(p_id);\r
166 }\r
167 \r
168 static NTSTATUS\r
169 cm_listen(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,\r
170                   uint8_t compare_len, uint8_t compare_offset)\r
171 {\r
172         ib_cep_listen_t info;\r
173         ib_api_status_t ib_status;\r
174 \r
175         info.svc_id = service_id;\r
176         info.port_guid = IB_ALL_PORTS;\r
177         info.p_cmp_buf = p_compare_buf;\r
178         info.cmp_len = compare_len;\r
179         info.cmp_offset = compare_offset;\r
180         \r
181         kal_cep_config(gh_al, p_id->cid, cm_listen_handler, p_id, cm_destroy_handler);\r
182         ib_status = al_cep_listen(gh_al, p_id->cid, &info);\r
183         return ib_to_ntstatus(ib_status);\r
184 }\r
185 \r
186 static NTSTATUS\r
187 cm_send_req(iba_cm_id *p_id, iba_cm_req *p_req)\r
188 {\r
189         ib_api_status_t ib_status;\r
190         \r
191         ib_status = kal_cep_pre_req(gh_al, p_id->cid, p_req, 0, NULL);\r
192         if (ib_status != IB_SUCCESS) {\r
193                 return ib_to_ntstatus(ib_status);\r
194         }\r
195 \r
196         ib_status = al_cep_send_req(gh_al, p_id->cid);\r
197         return ib_to_ntstatus(ib_status);\r
198 }\r
199 \r
200 static NTSTATUS\r
201 cm_send_rep(iba_cm_id *p_id, iba_cm_rep *p_rep)\r
202 {\r
203         ib_api_status_t ib_status;\r
204 \r
205         ib_status = kal_cep_pre_rep(gh_al, p_id->cid, p_rep, 0, NULL);\r
206         if (ib_status != IB_SUCCESS) {\r
207                 return ib_to_ntstatus(ib_status);\r
208         }\r
209 \r
210         ib_status = al_cep_send_rep(gh_al, p_id->cid);\r
211         return ib_to_ntstatus(ib_status);\r
212 }\r
213 \r
214 static NTSTATUS\r
215 cm_send_rtu(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
216 {\r
217         ib_api_status_t ib_status;\r
218 \r
219         ib_status = al_cep_rtu(gh_al, p_id->cid, p_pdata, pdata_len);\r
220         return ib_to_ntstatus(ib_status);\r
221 }\r
222 \r
223 static NTSTATUS\r
224 cm_send_dreq(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
225 {\r
226         ib_api_status_t ib_status;\r
227 \r
228         ib_status = al_cep_dreq(gh_al, p_id->cid, p_pdata, pdata_len);\r
229         return ib_to_ntstatus(ib_status);\r
230 }\r
231 \r
232 static NTSTATUS\r
233 cm_send_drep(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
234 {\r
235         ib_api_status_t ib_status;\r
236 \r
237         ib_status = al_cep_drep(gh_al, p_id->cid, p_pdata, pdata_len);\r
238         return ib_to_ntstatus(ib_status);\r
239 }\r
240 \r
241 static NTSTATUS\r
242 cm_send_rej(iba_cm_id *p_id, ib_rej_status_t status,\r
243                         void *p_ari, uint8_t ari_len,\r
244                         void *p_pdata, uint8_t pdata_len)\r
245 {\r
246         ib_api_status_t ib_status;\r
247 \r
248         ib_status = al_cep_rej(gh_al, p_id->cid, status, p_ari, ari_len,\r
249                                                    p_pdata, pdata_len);\r
250         return ib_to_ntstatus(ib_status);\r
251 }\r
252 \r
253 static NTSTATUS\r
254 cm_send_mra(iba_cm_id *p_id, uint8_t service_timeout,\r
255                         void *p_pdata, uint8_t pdata_len)\r
256 {\r
257         ib_cm_mra_t             mra;\r
258         ib_api_status_t ib_status;\r
259 \r
260         mra.svc_timeout = service_timeout;\r
261         mra.p_mra_pdata = p_pdata;\r
262         mra.mra_length = pdata_len;\r
263 \r
264         ib_status = al_cep_mra(gh_al, p_id->cid, &mra);\r
265         return ib_to_ntstatus(ib_status);\r
266 }\r
267 \r
268 static NTSTATUS\r
269 cm_send_lap(iba_cm_id *p_id, iba_cm_lap *p_lap)\r
270 {\r
271         ib_cm_lap_t             lap;\r
272         ib_api_status_t ib_status;\r
273 \r
274         RtlZeroMemory(&lap, sizeof lap);\r
275         lap.p_lap_pdata = p_lap->p_pdata;\r
276         lap.lap_length = p_lap->pdata_len;\r
277         lap.remote_resp_timeout = p_lap->remote_resp_timeout;\r
278         lap.p_alt_path = p_lap->p_alt_path;\r
279 \r
280         ib_status = al_cep_lap(gh_al, p_id->cid, &lap);\r
281         return ib_to_ntstatus(ib_status);\r
282 }\r
283 \r
284 static NTSTATUS\r
285 cm_send_apr(iba_cm_id *p_id, iba_cm_apr *p_apr)\r
286 {\r
287         ib_cm_apr_t             apr;\r
288         ib_qp_mod_t             attr;\r
289         ib_api_status_t ib_status;\r
290 \r
291         RtlZeroMemory(&apr, sizeof apr);\r
292         apr.p_apr_pdata = p_apr->p_pdata;\r
293         apr.apr_length = p_apr->pdata_len;\r
294         apr.apr_status = p_apr->status;\r
295         apr.info_length = p_apr->info_length;\r
296         apr.p_info = p_apr->p_info;\r
297 \r
298         ib_status = al_cep_pre_apr(gh_al, p_id->cid, &apr, &attr);\r
299         if (ib_status != IB_SUCCESS) {\r
300                 return ib_to_ntstatus(ib_status);\r
301         }\r
302 \r
303         ib_status = al_cep_send_apr(gh_al, p_id->cid);\r
304         return ib_to_ntstatus(ib_status);\r
305 }\r
306 \r
307 static NTSTATUS\r
308 cm_send_sidr_req(iba_cm_id *p_id, iba_cm_sidr_req *p_req)\r
309 {\r
310         UNUSED_PARAM(p_id);\r
311         UNUSED_PARAM(p_req);\r
312 \r
313         return STATUS_NOT_SUPPORTED;\r
314 }\r
315 \r
316 static NTSTATUS\r
317 cm_send_sidr_rep(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep)\r
318 {\r
319         UNUSED_PARAM(p_id);\r
320         UNUSED_PARAM(p_rep);\r
321 \r
322         return STATUS_NOT_SUPPORTED;\r
323 }\r
324 \r
325 static NTSTATUS\r
326 cm_get_qp_attr(iba_cm_id *p_id, ib_qp_state_t state, ib_qp_mod_t *p_attr)\r
327 {\r
328         ib_api_status_t ib_status;\r
329 \r
330         switch (state) {\r
331         case IB_QPS_INIT:\r
332                 ib_status = al_cep_get_init_attr(gh_al, p_id->cid, p_attr);\r
333                 break;\r
334         case IB_QPS_RTR:\r
335                 ib_status = al_cep_get_rtr_attr(gh_al, p_id->cid, p_attr);\r
336                 break;\r
337         case IB_QPS_RTS:\r
338                 ib_status = al_cep_get_rts_attr(gh_al, p_id->cid, p_attr);\r
339                 break;\r
340         default:\r
341                 return STATUS_INVALID_PARAMETER;\r
342         }\r
343 \r
344         return ib_to_ntstatus(ib_status);\r
345 }\r
346 \r
347 static NTSTATUS\r
348 cm_migrate(iba_cm_id *p_id)\r
349 {\r
350         ib_api_status_t ib_status;\r
351 \r
352         ib_status = al_cep_migrate(gh_al, p_id->cid);\r
353         return ib_to_ntstatus(ib_status);\r
354 }\r
355 \r
356 static NTSTATUS\r
357 cm_establish(iba_cm_id *p_id)\r
358 {\r
359         ib_api_status_t ib_status;\r
360 \r
361         ib_status = al_cep_established(gh_al, p_id->cid);\r
362         return ib_to_ntstatus(ib_status);\r
363 }\r
364 \r
365 void cm_get_interface(iba_cm_interface *p_ifc)\r
366 {\r
367         p_ifc->create_id = cm_create_id;\r
368         p_ifc->destroy_id = cm_destroy_id;\r
369         p_ifc->listen = cm_listen;\r
370         p_ifc->send_req = cm_send_req;\r
371         p_ifc->send_rep = cm_send_rep;\r
372         p_ifc->send_rtu = cm_send_rtu;\r
373         p_ifc->send_dreq = cm_send_dreq;\r
374         p_ifc->send_drep = cm_send_drep;\r
375         p_ifc->send_rej = cm_send_rej;\r
376         p_ifc->send_mra = cm_send_mra;\r
377         p_ifc->send_lap = cm_send_lap;\r
378         p_ifc->send_apr = cm_send_apr;\r
379         p_ifc->send_sidr_req = cm_send_sidr_req;\r
380         p_ifc->send_sidr_rep = cm_send_sidr_rep;\r
381         p_ifc->get_qp_attr = cm_get_qp_attr;\r
382         p_ifc->migrate = cm_migrate;\r
383         p_ifc->established = cm_establish;\r
384 }\r