Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / 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                 struct ib_sa_device *sa_dev;
410                 sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
411
412                 schedule_work(&sa_dev->port[event->element.port_num -
413                                             sa_dev->start_port].update_task);
414         }
415 }
416
417 /**
418  * ib_sa_cancel_query - try to cancel an SA query
419  * @id:ID of query to cancel
420  * @query:query pointer to cancel
421  *
422  * Try to cancel an SA query.  If the id and query don't match up or
423  * the query has already completed, nothing is done.  Otherwise the
424  * query is canceled and will complete with a status of -EINTR.
425  */
426 void ib_sa_cancel_query(int id, struct ib_sa_query *query)
427 {
428         unsigned long flags;
429         struct ib_mad_agent *agent;
430         struct ib_mad_send_buf *mad_buf;
431
432         spin_lock_irqsave(&idr_lock, flags);
433         if (idr_find(&query_idr, id) != query) {
434                 spin_unlock_irqrestore(&idr_lock, flags);
435                 return;
436         }
437         agent = query->port->agent;
438         mad_buf = query->mad_buf;
439         spin_unlock_irqrestore(&idr_lock, flags);
440
441         ib_cancel_mad(agent, mad_buf);
442 }
443 EXPORT_SYMBOL(ib_sa_cancel_query);
444
445 int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
446                          struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr)
447 {
448         int ret;
449         u16 gid_index;
450
451         memset(ah_attr, 0, sizeof *ah_attr);
452         ah_attr->dlid = be16_to_cpu(rec->dlid);
453         ah_attr->sl = rec->sl;
454         ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
455         ah_attr->port_num = port_num;
456
457         if (rec->hop_limit > 1) {
458                 ah_attr->ah_flags = IB_AH_GRH;
459                 ah_attr->grh.dgid = rec->dgid;
460
461                 ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
462                                          &gid_index);
463                 if (ret)
464                         return ret;
465
466                 ah_attr->grh.sgid_index    = gid_index;
467                 ah_attr->grh.flow_label    = be32_to_cpu(rec->flow_label);
468                 ah_attr->grh.hop_limit     = rec->hop_limit;
469                 ah_attr->grh.traffic_class = rec->traffic_class;
470         }
471         return 0;
472 }
473 EXPORT_SYMBOL(ib_init_ah_from_path);
474
475 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
476 {
477         unsigned long flags;
478
479         memset(mad, 0, sizeof *mad);
480
481         mad->mad_hdr.base_version  = IB_MGMT_BASE_VERSION;
482         mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_SUBN_ADM;
483         mad->mad_hdr.class_version = IB_SA_CLASS_VERSION;
484
485         spin_lock_irqsave(&tid_lock, flags);
486         mad->mad_hdr.tid           =
487                 cpu_to_be64(((u64) agent->hi_tid) << 32 | tid++);
488         spin_unlock_irqrestore(&tid_lock, flags);
489 }
490
491 static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
492 {
493         unsigned long flags;
494         int ret, id;
495
496 retry:
497         if (!idr_pre_get(&query_idr, gfp_mask))
498                 return -ENOMEM;
499         spin_lock_irqsave(&idr_lock, flags);
500         ret = idr_get_new(&query_idr, query, &id);
501         spin_unlock_irqrestore(&idr_lock, flags);
502         if (ret == -EAGAIN)
503                 goto retry;
504         if (ret)
505                 return ret;
506
507         query->mad_buf->timeout_ms  = timeout_ms;
508         query->mad_buf->context[0] = query;
509         query->id = id;
510
511         spin_lock_irqsave(&query->port->ah_lock, flags);
512         kref_get(&query->port->sm_ah->ref);
513         query->sm_ah = query->port->sm_ah;
514         spin_unlock_irqrestore(&query->port->ah_lock, flags);
515
516         query->mad_buf->ah = query->sm_ah->ah;
517
518         ret = ib_post_send_mad(query->mad_buf, NULL);
519         if (ret) {
520                 spin_lock_irqsave(&idr_lock, flags);
521                 idr_remove(&query_idr, id);
522                 spin_unlock_irqrestore(&idr_lock, flags);
523
524                 kref_put(&query->sm_ah->ref, free_sm_ah);
525         }
526
527         /*
528          * It's not safe to dereference query any more, because the
529          * send may already have completed and freed the query in
530          * another context.
531          */
532         return ret ? ret : id;
533 }
534
535 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
536                                     int status,
537                                     struct ib_sa_mad *mad)
538 {
539         struct ib_sa_path_query *query =
540                 container_of(sa_query, struct ib_sa_path_query, sa_query);
541
542         if (mad) {
543                 struct ib_sa_path_rec rec;
544
545                 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
546                           mad->data, &rec);
547                 query->callback(status, &rec, query->context);
548         } else
549                 query->callback(status, NULL, query->context);
550 }
551
552 static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
553 {
554         kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
555 }
556
557 /**
558  * ib_sa_path_rec_get - Start a Path get query
559  * @device:device to send query on
560  * @port_num: port number to send query on
561  * @rec:Path Record to send in query
562  * @comp_mask:component mask to send in query
563  * @timeout_ms:time to wait for response
564  * @gfp_mask:GFP mask to use for internal allocations
565  * @callback:function called when query completes, times out or is
566  * canceled
567  * @context:opaque user context passed to callback
568  * @sa_query:query context, used to cancel query
569  *
570  * Send a Path Record Get query to the SA to look up a path.  The
571  * callback function will be called when the query completes (or
572  * fails); status is 0 for a successful response, -EINTR if the query
573  * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
574  * occurred sending the query.  The resp parameter of the callback is
575  * only valid if status is 0.
576  *
577  * If the return value of ib_sa_path_rec_get() is negative, it is an
578  * error code.  Otherwise it is a query ID that can be used to cancel
579  * the query.
580  */
581 int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
582                        struct ib_sa_path_rec *rec,
583                        ib_sa_comp_mask comp_mask,
584                        int timeout_ms, gfp_t gfp_mask,
585                        void (*callback)(int status,
586                                         struct ib_sa_path_rec *resp,
587                                         void *context),
588                        void *context,
589                        struct ib_sa_query **sa_query)
590 {
591         struct ib_sa_path_query *query;
592         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
593         struct ib_sa_port   *port;
594         struct ib_mad_agent *agent;
595         struct ib_sa_mad *mad;
596         int ret;
597
598         if (!sa_dev)
599                 return -ENODEV;
600
601         port  = &sa_dev->port[port_num - sa_dev->start_port];
602         agent = port->agent;
603
604         query = kmalloc(sizeof *query, gfp_mask);
605         if (!query)
606                 return -ENOMEM;
607
608         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
609                                                      0, IB_MGMT_SA_HDR,
610                                                      IB_MGMT_SA_DATA, gfp_mask);
611         if (!query->sa_query.mad_buf) {
612                 ret = -ENOMEM;
613                 goto err1;
614         }
615
616         query->callback = callback;
617         query->context  = context;
618
619         mad = query->sa_query.mad_buf->mad;
620         init_mad(mad, agent);
621
622         query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
623         query->sa_query.release  = ib_sa_path_rec_release;
624         query->sa_query.port     = port;
625         mad->mad_hdr.method      = IB_MGMT_METHOD_GET;
626         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_PATH_REC);
627         mad->sa_hdr.comp_mask    = comp_mask;
628
629         ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
630
631         *sa_query = &query->sa_query;
632
633         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
634         if (ret < 0)
635                 goto err2;
636
637         return ret;
638
639 err2:
640         *sa_query = NULL;
641         ib_free_send_mad(query->sa_query.mad_buf);
642
643 err1:
644         kfree(query);
645         return ret;
646 }
647 EXPORT_SYMBOL(ib_sa_path_rec_get);
648
649 static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
650                                     int status,
651                                     struct ib_sa_mad *mad)
652 {
653         struct ib_sa_service_query *query =
654                 container_of(sa_query, struct ib_sa_service_query, sa_query);
655
656         if (mad) {
657                 struct ib_sa_service_rec rec;
658
659                 ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),
660                           mad->data, &rec);
661                 query->callback(status, &rec, query->context);
662         } else
663                 query->callback(status, NULL, query->context);
664 }
665
666 static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
667 {
668         kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
669 }
670
671 /**
672  * ib_sa_service_rec_query - Start Service Record operation
673  * @device:device to send request on
674  * @port_num: port number to send request on
675  * @method:SA method - should be get, set, or delete
676  * @rec:Service Record to send in request
677  * @comp_mask:component mask to send in request
678  * @timeout_ms:time to wait for response
679  * @gfp_mask:GFP mask to use for internal allocations
680  * @callback:function called when request completes, times out or is
681  * canceled
682  * @context:opaque user context passed to callback
683  * @sa_query:request context, used to cancel request
684  *
685  * Send a Service Record set/get/delete to the SA to register,
686  * unregister or query a service record.
687  * The callback function will be called when the request completes (or
688  * fails); status is 0 for a successful response, -EINTR if the query
689  * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
690  * occurred sending the query.  The resp parameter of the callback is
691  * only valid if status is 0.
692  *
693  * If the return value of ib_sa_service_rec_query() is negative, it is an
694  * error code.  Otherwise it is a request ID that can be used to cancel
695  * the query.
696  */
697 int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
698                             struct ib_sa_service_rec *rec,
699                             ib_sa_comp_mask comp_mask,
700                             int timeout_ms, gfp_t gfp_mask,
701                             void (*callback)(int status,
702                                              struct ib_sa_service_rec *resp,
703                                              void *context),
704                             void *context,
705                             struct ib_sa_query **sa_query)
706 {
707         struct ib_sa_service_query *query;
708         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
709         struct ib_sa_port   *port;
710         struct ib_mad_agent *agent;
711         struct ib_sa_mad *mad;
712         int ret;
713
714         if (!sa_dev)
715                 return -ENODEV;
716
717         port  = &sa_dev->port[port_num - sa_dev->start_port];
718         agent = port->agent;
719
720         if (method != IB_MGMT_METHOD_GET &&
721             method != IB_MGMT_METHOD_SET &&
722             method != IB_SA_METHOD_DELETE)
723                 return -EINVAL;
724
725         query = kmalloc(sizeof *query, gfp_mask);
726         if (!query)
727                 return -ENOMEM;
728
729         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
730                                                      0, IB_MGMT_SA_HDR,
731                                                      IB_MGMT_SA_DATA, gfp_mask);
732         if (!query->sa_query.mad_buf) {
733                 ret = -ENOMEM;
734                 goto err1;
735         }
736
737         query->callback = callback;
738         query->context  = context;
739
740         mad = query->sa_query.mad_buf->mad;
741         init_mad(mad, agent);
742
743         query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
744         query->sa_query.release  = ib_sa_service_rec_release;
745         query->sa_query.port     = port;
746         mad->mad_hdr.method      = method;
747         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
748         mad->sa_hdr.comp_mask    = comp_mask;
749
750         ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
751                 rec, mad->data);
752
753         *sa_query = &query->sa_query;
754
755         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
756         if (ret < 0)
757                 goto err2;
758
759         return ret;
760
761 err2:
762         *sa_query = NULL;
763         ib_free_send_mad(query->sa_query.mad_buf);
764
765 err1:
766         kfree(query);
767         return ret;
768 }
769 EXPORT_SYMBOL(ib_sa_service_rec_query);
770
771 static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
772                                         int status,
773                                         struct ib_sa_mad *mad)
774 {
775         struct ib_sa_mcmember_query *query =
776                 container_of(sa_query, struct ib_sa_mcmember_query, sa_query);
777
778         if (mad) {
779                 struct ib_sa_mcmember_rec rec;
780
781                 ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
782                           mad->data, &rec);
783                 query->callback(status, &rec, query->context);
784         } else
785                 query->callback(status, NULL, query->context);
786 }
787
788 static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
789 {
790         kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
791 }
792
793 int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
794                              u8 method,
795                              struct ib_sa_mcmember_rec *rec,
796                              ib_sa_comp_mask comp_mask,
797                              int timeout_ms, gfp_t gfp_mask,
798                              void (*callback)(int status,
799                                               struct ib_sa_mcmember_rec *resp,
800                                               void *context),
801                              void *context,
802                              struct ib_sa_query **sa_query)
803 {
804         struct ib_sa_mcmember_query *query;
805         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
806         struct ib_sa_port   *port;
807         struct ib_mad_agent *agent;
808         struct ib_sa_mad *mad;
809         int ret;
810
811         if (!sa_dev)
812                 return -ENODEV;
813
814         port  = &sa_dev->port[port_num - sa_dev->start_port];
815         agent = port->agent;
816
817         query = kmalloc(sizeof *query, gfp_mask);
818         if (!query)
819                 return -ENOMEM;
820
821         query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
822                                                      0, IB_MGMT_SA_HDR,
823                                                      IB_MGMT_SA_DATA, gfp_mask);
824         if (!query->sa_query.mad_buf) {
825                 ret = -ENOMEM;
826                 goto err1;
827         }
828
829         query->callback = callback;
830         query->context  = context;
831
832         mad = query->sa_query.mad_buf->mad;
833         init_mad(mad, agent);
834
835         query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
836         query->sa_query.release  = ib_sa_mcmember_rec_release;
837         query->sa_query.port     = port;
838         mad->mad_hdr.method      = method;
839         mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
840         mad->sa_hdr.comp_mask    = comp_mask;
841
842         ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
843                 rec, mad->data);
844
845         *sa_query = &query->sa_query;
846
847         ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
848         if (ret < 0)
849                 goto err2;
850
851         return ret;
852
853 err2:
854         *sa_query = NULL;
855         ib_free_send_mad(query->sa_query.mad_buf);
856
857 err1:
858         kfree(query);
859         return ret;
860 }
861 EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
862
863 static void send_handler(struct ib_mad_agent *agent,
864                          struct ib_mad_send_wc *mad_send_wc)
865 {
866         struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
867         unsigned long flags;
868
869         if (query->callback)
870                 switch (mad_send_wc->status) {
871                 case IB_WC_SUCCESS:
872                         /* No callback -- already got recv */
873                         break;
874                 case IB_WC_RESP_TIMEOUT_ERR:
875                         query->callback(query, -ETIMEDOUT, NULL);
876                         break;
877                 case IB_WC_WR_FLUSH_ERR:
878                         query->callback(query, -EINTR, NULL);
879                         break;
880                 default:
881                         query->callback(query, -EIO, NULL);
882                         break;
883                 }
884
885         spin_lock_irqsave(&idr_lock, flags);
886         idr_remove(&query_idr, query->id);
887         spin_unlock_irqrestore(&idr_lock, flags);
888
889         ib_free_send_mad(mad_send_wc->send_buf);
890         kref_put(&query->sm_ah->ref, free_sm_ah);
891         query->release(query);
892 }
893
894 static void recv_handler(struct ib_mad_agent *mad_agent,
895                          struct ib_mad_recv_wc *mad_recv_wc)
896 {
897         struct ib_sa_query *query;
898         struct ib_mad_send_buf *mad_buf;
899
900         mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
901         query = mad_buf->context[0];
902
903         if (query->callback) {
904                 if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
905                         query->callback(query,
906                                         mad_recv_wc->recv_buf.mad->mad_hdr.status ?
907                                         -EINVAL : 0,
908                                         (struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);
909                 else
910                         query->callback(query, -EIO, NULL);
911         }
912
913         ib_free_recv_mad(mad_recv_wc);
914 }
915
916 static void ib_sa_add_one(struct ib_device *device)
917 {
918         struct ib_sa_device *sa_dev;
919         int s, e, i;
920
921         if (device->node_type == IB_NODE_SWITCH)
922                 s = e = 0;
923         else {
924                 s = 1;
925                 e = device->phys_port_cnt;
926         }
927
928         sa_dev = kmalloc(sizeof *sa_dev +
929                          (e - s + 1) * sizeof (struct ib_sa_port),
930                          GFP_KERNEL);
931         if (!sa_dev)
932                 return;
933
934         sa_dev->start_port = s;
935         sa_dev->end_port   = e;
936
937         for (i = 0; i <= e - s; ++i) {
938                 sa_dev->port[i].sm_ah    = NULL;
939                 sa_dev->port[i].port_num = i + s;
940                 spin_lock_init(&sa_dev->port[i].ah_lock);
941
942                 sa_dev->port[i].agent =
943                         ib_register_mad_agent(device, i + s, IB_QPT_GSI,
944                                               NULL, 0, send_handler,
945                                               recv_handler, sa_dev);
946                 if (IS_ERR(sa_dev->port[i].agent))
947                         goto err;
948
949                 INIT_WORK(&sa_dev->port[i].update_task,
950                           update_sm_ah, &sa_dev->port[i]);
951         }
952
953         ib_set_client_data(device, &sa_client, sa_dev);
954
955         /*
956          * We register our event handler after everything is set up,
957          * and then update our cached info after the event handler is
958          * registered to avoid any problems if a port changes state
959          * during our initialization.
960          */
961
962         INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);
963         if (ib_register_event_handler(&sa_dev->event_handler))
964                 goto err;
965
966         for (i = 0; i <= e - s; ++i)
967                 update_sm_ah(&sa_dev->port[i]);
968
969         return;
970
971 err:
972         while (--i >= 0)
973                 ib_unregister_mad_agent(sa_dev->port[i].agent);
974
975         kfree(sa_dev);
976
977         return;
978 }
979
980 static void ib_sa_remove_one(struct ib_device *device)
981 {
982         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
983         int i;
984
985         if (!sa_dev)
986                 return;
987
988         ib_unregister_event_handler(&sa_dev->event_handler);
989
990         flush_scheduled_work();
991
992         for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
993                 ib_unregister_mad_agent(sa_dev->port[i].agent);
994                 kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
995         }
996
997         kfree(sa_dev);
998 }
999
1000 static int __init ib_sa_init(void)
1001 {
1002         int ret;
1003
1004         spin_lock_init(&idr_lock);
1005         spin_lock_init(&tid_lock);
1006
1007         get_random_bytes(&tid, sizeof tid);
1008
1009         ret = ib_register_client(&sa_client);
1010         if (ret)
1011                 printk(KERN_ERR "Couldn't register ib_sa client\n");
1012
1013         return ret;
1014 }
1015
1016 static void __exit ib_sa_cleanup(void)
1017 {
1018         ib_unregister_client(&sa_client);
1019         idr_destroy(&query_idr);
1020 }
1021
1022 module_init(ib_sa_init);
1023 module_exit(ib_sa_cleanup);