df762ba4868f8f57a1e83bd854418af87592e7b4
[linux-2.6.git] / drivers / infiniband / core / sa_query.c
1 /*
2  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  * $Id: sa_query.c 2811 2005-07-06 18:11:43Z halr $
34  */
35
36 #include <linux/module.h>
37 #include <linux/init.h>
38 #include <linux/err.h>
39 #include <linux/random.h>
40 #include <linux/spinlock.h>
41 #include <linux/slab.h>
42 #include <linux/pci.h>
43 #include <linux/dma-mapping.h>
44 #include <linux/kref.h>
45 #include <linux/idr.h>
46 #include <linux/workqueue.h>
47
48 #include <rdma/ib_pack.h>
49 #include <rdma/ib_sa.h>
50 #include <rdma/ib_cache.h>
51
52 MODULE_AUTHOR("Roland Dreier");
53 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
54 MODULE_LICENSE("Dual BSD/GPL");
55
56 struct ib_sa_sm_ah {
57         struct ib_ah        *ah;
58         struct kref          ref;
59 };
60
61 struct ib_sa_port {
62         struct ib_mad_agent *agent;
63         struct ib_sa_sm_ah  *sm_ah;
64         struct work_struct   update_task;
65         spinlock_t           ah_lock;
66         u8                   port_num;
67 };
68
69 struct ib_sa_device {
70         int                     start_port, end_port;
71         struct ib_event_handler event_handler;
72         struct ib_sa_port port[0];
73 };
74
75 struct ib_sa_query {
76         void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
77         void (*release)(struct ib_sa_query *);
78         struct ib_sa_port      *port;
79         struct ib_mad_send_buf *mad_buf;
80         struct ib_sa_sm_ah     *sm_ah;
81         int                     id;
82 };
83
84 struct ib_sa_service_query {
85         void (*callback)(int, struct ib_sa_service_rec *, void *);
86         void *context;
87         struct ib_sa_query sa_query;
88 };
89
90 struct ib_sa_path_query {
91         void (*callback)(int, struct ib_sa_path_rec *, void *);
92         void *context;
93         struct ib_sa_query sa_query;
94 };
95
96 struct ib_sa_mcmember_query {
97         void (*callback)(int, struct ib_sa_mcmember_rec *, void *);
98         void *context;
99         struct ib_sa_query sa_query;
100 };
101
102 static void ib_sa_add_one(struct ib_device *device);
103 static void ib_sa_remove_one(struct ib_device *device);
104
105 static struct ib_client sa_client = {
106         .name   = "sa",
107         .add    = ib_sa_add_one,
108         .remove = ib_sa_remove_one
109 };
110
111 static spinlock_t idr_lock;
112 static DEFINE_IDR(query_idr);
113
114 static spinlock_t tid_lock;
115 static u32 tid;
116
117 #define PATH_REC_FIELD(field) \
118         .struct_offset_bytes = offsetof(struct ib_sa_path_rec, field),          \
119         .struct_size_bytes   = sizeof ((struct ib_sa_path_rec *) 0)->field,     \
120         .field_name          = "sa_path_rec:" #field
121
122 static const struct ib_field path_rec_table[] = {
123         { RESERVED,
124           .offset_words = 0,
125           .offset_bits  = 0,
126           .size_bits    = 32 },
127         { RESERVED,
128           .offset_words = 1,
129           .offset_bits  = 0,
130           .size_bits    = 32 },
131         { PATH_REC_FIELD(dgid),
132           .offset_words = 2,
133           .offset_bits  = 0,
134           .size_bits    = 128 },
135         { PATH_REC_FIELD(sgid),
136           .offset_words = 6,
137           .offset_bits  = 0,
138           .size_bits    = 128 },
139         { PATH_REC_FIELD(dlid),
140           .offset_words = 10,
141           .offset_bits  = 0,
142           .size_bits    = 16 },
143         { PATH_REC_FIELD(slid),
144           .offset_words = 10,
145           .offset_bits  = 16,
146           .size_bits    = 16 },
147         { PATH_REC_FIELD(raw_traffic),
148           .offset_words = 11,
149           .offset_bits  = 0,
150           .size_bits    = 1 },
151         { RESERVED,
152           .offset_words = 11,
153           .offset_bits  = 1,
154           .size_bits    = 3 },
155         { PATH_REC_FIELD(flow_label),
156           .offset_words = 11,
157           .offset_bits  = 4,
158           .size_bits    = 20 },
159         { PATH_REC_FIELD(hop_limit),
160           .offset_words = 11,
161           .offset_bits  = 24,
162           .size_bits    = 8 },
163         { PATH_REC_FIELD(traffic_class),
164           .offset_words = 12,
165           .offset_bits  = 0,
166           .size_bits    = 8 },
167         { PATH_REC_FIELD(reversible),
168           .offset_words = 12,
169           .offset_bits  = 8,
170           .size_bits    = 1 },
171         { PATH_REC_FIELD(numb_path),
172           .offset_words = 12,
173           .offset_bits  = 9,
174           .size_bits    = 7 },
175         { PATH_REC_FIELD(pkey),
176           .offset_words = 12,
177           .offset_bits  = 16,
178           .size_bits    = 16 },
179         { RESERVED,
180           .offset_words = 13,
181           .offset_bits  = 0,
182           .size_bits    = 12 },
183         { PATH_REC_FIELD(sl),
184           .offset_words = 13,
185           .offset_bits  = 12,
186           .size_bits    = 4 },
187         { PATH_REC_FIELD(mtu_selector),
188           .offset_words = 13,
189           .offset_bits  = 16,
190           .size_bits    = 2 },
191         { PATH_REC_FIELD(mtu),
192           .offset_words = 13,
193           .offset_bits  = 18,
194           .size_bits    = 6 },
195         { PATH_REC_FIELD(rate_selector),
196           .offset_words = 13,
197           .offset_bits  = 24,
198           .size_bits    = 2 },
199         { PATH_REC_FIELD(rate),
200           .offset_words = 13,
201           .offset_bits  = 26,
202           .size_bits    = 6 },
203         { PATH_REC_FIELD(packet_life_time_selector),
204           .offset_words = 14,
205           .offset_bits  = 0,
206           .size_bits    = 2 },
207         { PATH_REC_FIELD(packet_life_time),
208           .offset_words = 14,
209           .offset_bits  = 2,
210           .size_bits    = 6 },
211         { PATH_REC_FIELD(preference),
212           .offset_words = 14,
213           .offset_bits  = 8,
214           .size_bits    = 8 },
215         { RESERVED,
216           .offset_words = 14,
217           .offset_bits  = 16,
218           .size_bits    = 48 },
219 };
220
221 #define MCMEMBER_REC_FIELD(field) \
222         .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field),      \
223         .struct_size_bytes   = sizeof ((struct ib_sa_mcmember_rec *) 0)->field, \
224         .field_name          = "sa_mcmember_rec:" #field
225
226 static const struct ib_field mcmember_rec_table[] = {
227         { MCMEMBER_REC_FIELD(mgid),
228           .offset_words = 0,
229           .offset_bits  = 0,
230           .size_bits    = 128 },
231         { MCMEMBER_REC_FIELD(port_gid),
232           .offset_words = 4,
233           .offset_bits  = 0,
234           .size_bits    = 128 },
235         { MCMEMBER_REC_FIELD(qkey),
236           .offset_words = 8,
237           .offset_bits  = 0,
238           .size_bits    = 32 },
239         { MCMEMBER_REC_FIELD(mlid),
240           .offset_words = 9,
241           .offset_bits  = 0,
242           .size_bits    = 16 },
243         { MCMEMBER_REC_FIELD(mtu_selector),
244           .offset_words = 9,
245           .offset_bits  = 16,
246           .size_bits    = 2 },
247         { MCMEMBER_REC_FIELD(mtu),
248           .offset_words = 9,
249           .offset_bits  = 18,
250           .size_bits    = 6 },
251         { MCMEMBER_REC_FIELD(traffic_class),
252           .offset_words = 9,
253           .offset_bits  = 24,
254           .size_bits    = 8 },
255         { MCMEMBER_REC_FIELD(pkey),
256           .offset_words = 10,
257           .offset_bits  = 0,
258           .size_bits    = 16 },
259         { MCMEMBER_REC_FIELD(rate_selector),
260           .offset_words = 10,
261           .offset_bits  = 16,
262           .size_bits    = 2 },
263         { MCMEMBER_REC_FIELD(rate),
264           .offset_words = 10,
265           .offset_bits  = 18,
266           .size_bits    = 6 },
267         { MCMEMBER_REC_FIELD(packet_life_time_selector),
268           .offset_words = 10,
269           .offset_bits  = 24,
270           .size_bits    = 2 },
271         { MCMEMBER_REC_FIELD(packet_life_time),
272           .offset_words = 10,
273           .offset_bits  = 26,
274           .size_bits    = 6 },
275         { MCMEMBER_REC_FIELD(sl),
276           .offset_words = 11,
277           .offset_bits  = 0,
278           .size_bits    = 4 },
279         { MCMEMBER_REC_FIELD(flow_label),
280           .offset_words = 11,
281           .offset_bits  = 4,
282           .size_bits    = 20 },
283         { MCMEMBER_REC_FIELD(hop_limit),
284           .offset_words = 11,
285           .offset_bits  = 24,
286           .size_bits    = 8 },
287         { MCMEMBER_REC_FIELD(scope),
288           .offset_words = 12,
289           .offset_bits  = 0,
290           .size_bits    = 4 },
291         { MCMEMBER_REC_FIELD(join_state),
292           .offset_words = 12,
293           .offset_bits  = 4,
294           .size_bits    = 4 },
295         { MCMEMBER_REC_FIELD(proxy_join),
296           .offset_words = 12,
297           .offset_bits  = 8,
298           .size_bits    = 1 },
299         { RESERVED,
300           .offset_words = 12,
301           .offset_bits  = 9,
302           .size_bits    = 23 },
303 };
304
305 #define SERVICE_REC_FIELD(field) \
306         .struct_offset_bytes = offsetof(struct ib_sa_service_rec, field),       \
307         .struct_size_bytes   = sizeof ((struct ib_sa_service_rec *) 0)->field,  \
308         .field_name          = "sa_service_rec:" #field
309
310 static const struct ib_field service_rec_table[] = {
311         { SERVICE_REC_FIELD(id),
312           .offset_words = 0,
313           .offset_bits  = 0,
314           .size_bits    = 64 },
315         { SERVICE_REC_FIELD(gid),
316           .offset_words = 2,
317           .offset_bits  = 0,
318           .size_bits    = 128 },
319         { SERVICE_REC_FIELD(pkey),
320           .offset_words = 6,
321           .offset_bits  = 0,
322           .size_bits    = 16 },
323         { SERVICE_REC_FIELD(lease),
324           .offset_words = 7,
325           .offset_bits  = 0,
326           .size_bits    = 32 },
327         { SERVICE_REC_FIELD(key),
328           .offset_words = 8,
329           .offset_bits  = 0,
330           .size_bits    = 128 },
331         { SERVICE_REC_FIELD(name),
332           .offset_words = 12,
333           .offset_bits  = 0,
334           .size_bits    = 64*8 },
335         { SERVICE_REC_FIELD(data8),
336           .offset_words = 28,
337           .offset_bits  = 0,
338           .size_bits    = 16*8 },
339         { SERVICE_REC_FIELD(data16),
340           .offset_words = 32,
341           .offset_bits  = 0,
342           .size_bits    = 8*16 },
343         { SERVICE_REC_FIELD(data32),
344           .offset_words = 36,
345           .offset_bits  = 0,
346           .size_bits    = 4*32 },
347         { SERVICE_REC_FIELD(data64),
348           .offset_words = 40,
349           .offset_bits  = 0,
350           .size_bits    = 2*64 },
351 };
352
353 static void free_sm_ah(struct kref *kref)
354 {
355         struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
356
357         ib_destroy_ah(sm_ah->ah);
358         kfree(sm_ah);
359 }
360
361 static void update_sm_ah(void *port_ptr)
362 {
363         struct ib_sa_port *port = port_ptr;
364         struct ib_sa_sm_ah *new_ah, *old_ah;
365         struct ib_port_attr port_attr;
366         struct ib_ah_attr   ah_attr;
367
368         if (ib_query_port(port->agent->device, port->port_num, &port_attr)) {
369                 printk(KERN_WARNING "Couldn't query port\n");
370                 return;
371         }
372
373         new_ah = kmalloc(sizeof *new_ah, GFP_KERNEL);
374         if (!new_ah) {
375                 printk(KERN_WARNING "Couldn't allocate new SM AH\n");
376                 return;
377         }
378
379         kref_init(&new_ah->ref);
380
381         memset(&ah_attr, 0, sizeof ah_attr);
382         ah_attr.dlid     = port_attr.sm_lid;
383         ah_attr.sl       = port_attr.sm_sl;
384         ah_attr.port_num = port->port_num;
385
386         new_ah->ah = ib_create_ah(port->agent->qp->pd, &ah_attr);
387         if (IS_ERR(new_ah->ah)) {
388                 printk(KERN_WARNING "Couldn't create new SM AH\n");
389                 kfree(new_ah);
390                 return;
391         }
392
393         spin_lock_irq(&port->ah_lock);
394         old_ah = port->sm_ah;
395         port->sm_ah = new_ah;
396         spin_unlock_irq(&port->ah_lock);
397
398         if (old_ah)
399                 kref_put(&old_ah->ref, free_sm_ah);
400 }
401
402 static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event)
403 {
404         if (event->event == IB_EVENT_PORT_ERR    ||
405             event->event == IB_EVENT_PORT_ACTIVE ||
406             event->event == IB_EVENT_LID_CHANGE  ||
407             event->event == IB_EVENT_PKEY_CHANGE ||
408             event->event == IB_EVENT_SM_CHANGE   ||
409             event->event == IB_EVENT_CLIENT_REREGISTER) {
410                 struct ib_sa_device *sa_dev;
411                 sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
412
413                 schedule_work(&sa_dev->port[event->element.port_num -
414                                             sa_dev->start_port].update_task);
415         }
416 }
417
418 /**
419  * ib_sa_cancel_query - try to cancel an SA query
420  * @id:ID of query to cancel
421  * @query:query pointer to cancel
422  *
423  * Try to cancel an SA query.  If the id and query don't match up or
424  * the query has already completed, nothing is done.  Otherwise the
425  * query is canceled and will complete with a status of -EINTR.
426  */
427 void ib_sa_cancel_query(int id, struct ib_sa_query *query)
428 {
429         unsigned long flags;
430         struct ib_mad_agent *agent;
431         struct ib_mad_send_buf *mad_buf;
432
433         spin_lock_irqsave(&idr_lock, flags);
434         if (idr_find(&query_idr, id) != query) {
435                 spin_unlock_irqrestore(&idr_lock, flags);
436                 return;
437         }
438         agent = query->port->agent;
439         mad_buf = query->mad_buf;
440         spin_unlock_irqrestore(&idr_lock, flags);
441
442         ib_cancel_mad(agent, mad_buf);
443 }
444 EXPORT_SYMBOL(ib_sa_cancel_query);
445
446 int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
447                          struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr)
448 {
449         int ret;
450         u16 gid_index;
451
452         memset(ah_attr, 0, sizeof *ah_attr);
453         ah_attr->dlid = be16_to_cpu(rec->dlid);
454         ah_attr->sl = rec->sl;
455         ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
456         ah_attr->port_num = port_num;
457
458         if (rec->hop_limit > 1) {
459                 ah_attr->ah_flags = IB_AH_GRH;
460                 ah_attr->grh.dgid = rec->dgid;
461
462                 ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
463                                          &gid_index);
464                 if (ret)
465                         return ret;
466
467                 ah_attr->grh.sgid_index    = gid_index;
468                 ah_attr->grh.flow_label    = be32_to_cpu(rec->flow_label);
469                 ah_attr->grh.hop_limit     = rec->hop_limit;
470                 ah_attr->grh.traffic_class = rec->traffic_class;
471         }
472         return 0;
473 }
474 EXPORT_SYMBOL(ib_init_ah_from_path);
475
476 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
477 {
478         unsigned long flags;
479
480         memset(mad, 0, sizeof *mad);
481
482         mad->mad_hdr.base_version  = IB_MGMT_BASE_VERSION;
483         mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_SUBN_ADM;
484         mad->mad_hdr.class_version = IB_SA_CLASS_VERSION;
485
486         spin_lock_irqsave(&tid_lock, flags);
487         mad->mad_hdr.tid           =
488                 cpu_to_be64(((u64) agent->hi_tid) << 32 | tid++);
489         spin_unlock_irqrestore(&tid_lock, flags);
490 }
491
492 static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
493 {
494         unsigned long flags;
495         int ret, id;
496
497 retry:
498         if (!idr_pre_get(&query_idr, gfp_mask))
499                 return -ENOMEM;
500         spin_lock_irqsave(&idr_lock, flags);
501         ret = idr_get_new(&query_idr, query, &id);
502         spin_unlock_irqrestore(&idr_lock, flags);
503         if (ret == -EAGAIN)
504                 goto retry;
505         if (ret)
506                 return ret;
507
508         query->mad_buf->timeout_ms  = timeout_ms;
509         query->mad_buf->context[0] = query;
510         query->id = id;
511
512         spin_lock_irqsave(&query->port->ah_lock, flags);
513         kref_get(&query->port->sm_ah->ref);
514         query->sm_ah = query->port->sm_ah;
515         spin_unlock_irqrestore(&query->port->ah_lock, flags);
516
517         query->mad_buf->ah = query->sm_ah->ah;
518
519         ret = ib_post_send_mad(query->mad_buf, NULL);
520         if (ret) {
521                 spin_lock_irqsave(&idr_lock, flags);
522                 idr_remove(&query_idr, id);
523                 spin_unlock_irqrestore(&idr_lock, flags);
524
525                 kref_put(&query->sm_ah->ref, free_sm_ah);
526         }
527
528         /*
529          * It's not safe to dereference query any more, because the
530          * send may already have completed and freed the query in
531          * another context.
532          */
533         return ret ? ret : id;
534 }
535
536 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
537                                     int status,
538                                     struct ib_sa_mad *mad)
539 {
540         struct ib_sa_path_query *query =
541                 container_of(sa_query, struct ib_sa_path_query, sa_query);
542
543         if (mad) {
544                 struct ib_sa_path_rec rec;
545
546                 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
547                           mad->data, &rec);
548                 query->callback(status, &rec, query->context);
549         } else
550                 query->callback(status, NULL, query->context);
551 }
552
553 static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
554 {
555         kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
556 }
557
558 /**
559  * ib_sa_path_rec_get - Start a Path get query
560  * @device:device to send query on
561  * @port_num: port number to send query on
562  * @rec:Path Record to send in query
563  * @comp_mask:component mask to send in query
564  * @timeout_ms:time to wait for response
565  * @gfp_mask:GFP mask to use for internal allocations
566  * @callback:function called when query completes, times out or is
567  * canceled
568  * @context:opaque user context passed to callback
569  * @sa_query:query context, used to cancel query
570  *
571  * Send a Path Record Get query to the SA to look up a path.  The
572  * callback function will be called when the query completes (or
573  * fails); status is 0 for a successful response, -EINTR if the query
574  * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
575  * occurred sending the query.  The resp parameter of the callback is
576  * only valid if status is 0.
577  *
578  * If the return value of ib_sa_path_rec_get() is negative, it is an
579  * error code.  Otherwise it is a query ID that can be used to cancel
580  * the query.
581  */
582 int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
583                        struct ib_sa_path_rec *rec,
584                        ib_sa_comp_mask comp_mask,
585                        int timeout_ms, gfp_t gfp_mask,
586                        void (*callback)(int status,
587                                         struct ib_sa_path_rec *resp,
588                                         void *context),
589                        void *context,
590                        struct ib_sa_query **sa_query)
591 {
592         struct ib_sa_path_query *query;
593         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
594         struct ib_sa_port   *port;
595         struct ib_mad_agent *agent;
596         struct ib_sa_mad *mad;
597         int ret;
598
599         if (!sa_dev)
600                 return -ENODEV;
601
602         port  = &sa_dev->port[port_num - sa_dev->start_port];
603         agent = port->agent;
604
605         query = kmalloc(sizeof *query, gfp_mask);
606         if (!query)
607                 return -ENOMEM;
608
609         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
610                                                      0, IB_MGMT_SA_HDR,
611                                                      IB_MGMT_SA_DATA, gfp_mask);
612         if (!query->sa_query.mad_buf) {
613                 ret = -ENOMEM;
614                 goto err1;
615         }
616
617         query->callback = callback;
618         query->context  = context;
619
620         mad = query->sa_query.mad_buf->mad;
621         init_mad(mad, agent);
622
623         query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
624         query->sa_query.release  = ib_sa_path_rec_release;
625         query->sa_query.port     = port;
626         mad->mad_hdr.method      = IB_MGMT_METHOD_GET;
627         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_PATH_REC);
628         mad->sa_hdr.comp_mask    = comp_mask;
629
630         ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
631
632         *sa_query = &query->sa_query;
633
634         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
635         if (ret < 0)
636                 goto err2;
637
638         return ret;
639
640 err2:
641         *sa_query = NULL;
642         ib_free_send_mad(query->sa_query.mad_buf);
643
644 err1:
645         kfree(query);
646         return ret;
647 }
648 EXPORT_SYMBOL(ib_sa_path_rec_get);
649
650 static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
651                                     int status,
652                                     struct ib_sa_mad *mad)
653 {
654         struct ib_sa_service_query *query =
655                 container_of(sa_query, struct ib_sa_service_query, sa_query);
656
657         if (mad) {
658                 struct ib_sa_service_rec rec;
659
660                 ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),
661                           mad->data, &rec);
662                 query->callback(status, &rec, query->context);
663         } else
664                 query->callback(status, NULL, query->context);
665 }
666
667 static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
668 {
669         kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
670 }
671
672 /**
673  * ib_sa_service_rec_query - Start Service Record operation
674  * @device:device to send request on
675  * @port_num: port number to send request on
676  * @method:SA method - should be get, set, or delete
677  * @rec:Service Record to send in request
678  * @comp_mask:component mask to send in request
679  * @timeout_ms:time to wait for response
680  * @gfp_mask:GFP mask to use for internal allocations
681  * @callback:function called when request completes, times out or is
682  * canceled
683  * @context:opaque user context passed to callback
684  * @sa_query:request context, used to cancel request
685  *
686  * Send a Service Record set/get/delete to the SA to register,
687  * unregister or query a service record.
688  * The callback function will be called when the request completes (or
689  * fails); status is 0 for a successful response, -EINTR if the query
690  * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
691  * occurred sending the query.  The resp parameter of the callback is
692  * only valid if status is 0.
693  *
694  * If the return value of ib_sa_service_rec_query() is negative, it is an
695  * error code.  Otherwise it is a request ID that can be used to cancel
696  * the query.
697  */
698 int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
699                             struct ib_sa_service_rec *rec,
700                             ib_sa_comp_mask comp_mask,
701                             int timeout_ms, gfp_t gfp_mask,
702                             void (*callback)(int status,
703                                              struct ib_sa_service_rec *resp,
704                                              void *context),
705                             void *context,
706                             struct ib_sa_query **sa_query)
707 {
708         struct ib_sa_service_query *query;
709         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
710         struct ib_sa_port   *port;
711         struct ib_mad_agent *agent;
712         struct ib_sa_mad *mad;
713         int ret;
714
715         if (!sa_dev)
716                 return -ENODEV;
717
718         port  = &sa_dev->port[port_num - sa_dev->start_port];
719         agent = port->agent;
720
721         if (method != IB_MGMT_METHOD_GET &&
722             method != IB_MGMT_METHOD_SET &&
723             method != IB_SA_METHOD_DELETE)
724                 return -EINVAL;
725
726         query = kmalloc(sizeof *query, gfp_mask);
727         if (!query)
728                 return -ENOMEM;
729
730         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
731                                                      0, IB_MGMT_SA_HDR,
732                                                      IB_MGMT_SA_DATA, gfp_mask);
733         if (!query->sa_query.mad_buf) {
734                 ret = -ENOMEM;
735                 goto err1;
736         }
737
738         query->callback = callback;
739         query->context  = context;
740
741         mad = query->sa_query.mad_buf->mad;
742         init_mad(mad, agent);
743
744         query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
745         query->sa_query.release  = ib_sa_service_rec_release;
746         query->sa_query.port     = port;
747         mad->mad_hdr.method      = method;
748         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
749         mad->sa_hdr.comp_mask    = comp_mask;
750
751         ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
752                 rec, mad->data);
753
754         *sa_query = &query->sa_query;
755
756         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
757         if (ret < 0)
758                 goto err2;
759
760         return ret;
761
762 err2:
763         *sa_query = NULL;
764         ib_free_send_mad(query->sa_query.mad_buf);
765
766 err1:
767         kfree(query);
768         return ret;
769 }
770 EXPORT_SYMBOL(ib_sa_service_rec_query);
771
772 static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
773                                         int status,
774                                         struct ib_sa_mad *mad)
775 {
776         struct ib_sa_mcmember_query *query =
777                 container_of(sa_query, struct ib_sa_mcmember_query, sa_query);
778
779         if (mad) {
780                 struct ib_sa_mcmember_rec rec;
781
782                 ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
783                           mad->data, &rec);
784                 query->callback(status, &rec, query->context);
785         } else
786                 query->callback(status, NULL, query->context);
787 }
788
789 static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
790 {
791         kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
792 }
793
794 int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
795                              u8 method,
796                              struct ib_sa_mcmember_rec *rec,
797                              ib_sa_comp_mask comp_mask,
798                              int timeout_ms, gfp_t gfp_mask,
799                              void (*callback)(int status,
800                                               struct ib_sa_mcmember_rec *resp,
801                                               void *context),
802                              void *context,
803                              struct ib_sa_query **sa_query)
804 {
805         struct ib_sa_mcmember_query *query;
806         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
807         struct ib_sa_port   *port;
808         struct ib_mad_agent *agent;
809         struct ib_sa_mad *mad;
810         int ret;
811
812         if (!sa_dev)
813                 return -ENODEV;
814
815         port  = &sa_dev->port[port_num - sa_dev->start_port];
816         agent = port->agent;
817
818         query = kmalloc(sizeof *query, gfp_mask);
819         if (!query)
820                 return -ENOMEM;
821
822         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
823                                                      0, IB_MGMT_SA_HDR,
824                                                      IB_MGMT_SA_DATA, gfp_mask);
825         if (!query->sa_query.mad_buf) {
826                 ret = -ENOMEM;
827                 goto err1;
828         }
829
830         query->callback = callback;
831         query->context  = context;
832
833         mad = query->sa_query.mad_buf->mad;
834         init_mad(mad, agent);
835
836         query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
837         query->sa_query.release  = ib_sa_mcmember_rec_release;
838         query->sa_query.port     = port;
839         mad->mad_hdr.method      = method;
840         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
841         mad->sa_hdr.comp_mask    = comp_mask;
842
843         ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
844                 rec, mad->data);
845
846         *sa_query = &query->sa_query;
847
848         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
849         if (ret < 0)
850                 goto err2;
851
852         return ret;
853
854 err2:
855         *sa_query = NULL;
856         ib_free_send_mad(query->sa_query.mad_buf);
857
858 err1:
859         kfree(query);
860         return ret;
861 }
862 EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
863
864 static void send_handler(struct ib_mad_agent *agent,
865                          struct ib_mad_send_wc *mad_send_wc)
866 {
867         struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
868         unsigned long flags;
869
870         if (query->callback)
871                 switch (mad_send_wc->status) {
872                 case IB_WC_SUCCESS:
873                         /* No callback -- already got recv */
874                         break;
875                 case IB_WC_RESP_TIMEOUT_ERR:
876                         query->callback(query, -ETIMEDOUT, NULL);
877                         break;
878                 case IB_WC_WR_FLUSH_ERR:
879                         query->callback(query, -EINTR, NULL);
880                         break;
881                 default:
882                         query->callback(query, -EIO, NULL);
883                         break;
884                 }
885
886         spin_lock_irqsave(&idr_lock, flags);
887         idr_remove(&query_idr, query->id);
888         spin_unlock_irqrestore(&idr_lock, flags);
889
890         ib_free_send_mad(mad_send_wc->send_buf);
891         kref_put(&query->sm_ah->ref, free_sm_ah);
892         query->release(query);
893 }
894
895 static void recv_handler(struct ib_mad_agent *mad_agent,
896                          struct ib_mad_recv_wc *mad_recv_wc)
897 {
898         struct ib_sa_query *query;
899         struct ib_mad_send_buf *mad_buf;
900
901         mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
902         query = mad_buf->context[0];
903
904         if (query->callback) {
905                 if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
906                         query->callback(query,
907                                         mad_recv_wc->recv_buf.mad->mad_hdr.status ?
908                                         -EINVAL : 0,
909                                         (struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);
910                 else
911                         query->callback(query, -EIO, NULL);
912         }
913
914         ib_free_recv_mad(mad_recv_wc);
915 }
916
917 static void ib_sa_add_one(struct ib_device *device)
918 {
919         struct ib_sa_device *sa_dev;
920         int s, e, i;
921
922         if (device->node_type == IB_NODE_SWITCH)
923                 s = e = 0;
924         else {
925                 s = 1;
926                 e = device->phys_port_cnt;
927         }
928
929         sa_dev = kmalloc(sizeof *sa_dev +
930                          (e - s + 1) * sizeof (struct ib_sa_port),
931                          GFP_KERNEL);
932         if (!sa_dev)
933                 return;
934
935         sa_dev->start_port = s;
936         sa_dev->end_port   = e;
937
938         for (i = 0; i <= e - s; ++i) {
939                 sa_dev->port[i].sm_ah    = NULL;
940                 sa_dev->port[i].port_num = i + s;
941                 spin_lock_init(&sa_dev->port[i].ah_lock);
942
943                 sa_dev->port[i].agent =
944                         ib_register_mad_agent(device, i + s, IB_QPT_GSI,
945                                               NULL, 0, send_handler,
946                                               recv_handler, sa_dev);
947                 if (IS_ERR(sa_dev->port[i].agent))
948                         goto err;
949
950                 INIT_WORK(&sa_dev->port[i].update_task,
951                           update_sm_ah, &sa_dev->port[i]);
952         }
953
954         ib_set_client_data(device, &sa_client, sa_dev);
955
956         /*
957          * We register our event handler after everything is set up,
958          * and then update our cached info after the event handler is
959          * registered to avoid any problems if a port changes state
960          * during our initialization.
961          */
962
963         INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);
964         if (ib_register_event_handler(&sa_dev->event_handler))
965                 goto err;
966
967         for (i = 0; i <= e - s; ++i)
968                 update_sm_ah(&sa_dev->port[i]);
969
970         return;
971
972 err:
973         while (--i >= 0)
974                 ib_unregister_mad_agent(sa_dev->port[i].agent);
975
976         kfree(sa_dev);
977
978         return;
979 }
980
981 static void ib_sa_remove_one(struct ib_device *device)
982 {
983         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
984         int i;
985
986         if (!sa_dev)
987                 return;
988
989         ib_unregister_event_handler(&sa_dev->event_handler);
990
991         flush_scheduled_work();
992
993         for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
994                 ib_unregister_mad_agent(sa_dev->port[i].agent);
995                 kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
996         }
997
998         kfree(sa_dev);
999 }
1000
1001 static int __init ib_sa_init(void)
1002 {
1003         int ret;
1004
1005         spin_lock_init(&idr_lock);
1006         spin_lock_init(&tid_lock);
1007
1008         get_random_bytes(&tid, sizeof tid);
1009
1010         ret = ib_register_client(&sa_client);
1011         if (ret)
1012                 printk(KERN_ERR "Couldn't register ib_sa client\n");
1013
1014         return ret;
1015 }
1016
1017 static void __exit ib_sa_cleanup(void)
1018 {
1019         ib_unregister_client(&sa_client);
1020         idr_destroy(&query_idr);
1021 }
1022
1023 module_init(ib_sa_init);
1024 module_exit(ib_sa_cleanup);