]> err.no Git - linux-2.6/blob - drivers/infiniband/core/sa_query.c
[PATCH] IB: Introduce RMPP APIs
[linux-2.6] / drivers / infiniband / core / sa_query.c
1 /*
2  * Copyright (c) 2004 Topspin Communications.  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  * $Id: sa_query.c 1389 2004-12-27 22:56:47Z roland $
33  */
34
35 #include <linux/module.h>
36 #include <linux/init.h>
37 #include <linux/err.h>
38 #include <linux/random.h>
39 #include <linux/spinlock.h>
40 #include <linux/slab.h>
41 #include <linux/pci.h>
42 #include <linux/dma-mapping.h>
43 #include <linux/kref.h>
44 #include <linux/idr.h>
45
46 #include <ib_pack.h>
47 #include <ib_sa.h>
48
49 MODULE_AUTHOR("Roland Dreier");
50 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
51 MODULE_LICENSE("Dual BSD/GPL");
52
53 struct ib_sa_sm_ah {
54         struct ib_ah        *ah;
55         struct kref          ref;
56 };
57
58 struct ib_sa_port {
59         struct ib_mad_agent *agent;
60         struct ib_sa_sm_ah  *sm_ah;
61         struct work_struct   update_task;
62         spinlock_t           ah_lock;
63         u8                   port_num;
64 };
65
66 struct ib_sa_device {
67         int                     start_port, end_port;
68         struct ib_event_handler event_handler;
69         struct ib_sa_port port[0];
70 };
71
72 struct ib_sa_query {
73         void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
74         void (*release)(struct ib_sa_query *);
75         struct ib_sa_port  *port;
76         struct ib_sa_mad   *mad;
77         struct ib_sa_sm_ah *sm_ah;
78         DECLARE_PCI_UNMAP_ADDR(mapping)
79         int                 id;
80 };
81
82 struct ib_sa_path_query {
83         void (*callback)(int, struct ib_sa_path_rec *, void *);
84         void *context;
85         struct ib_sa_query sa_query;
86 };
87
88 struct ib_sa_mcmember_query {
89         void (*callback)(int, struct ib_sa_mcmember_rec *, void *);
90         void *context;
91         struct ib_sa_query sa_query;
92 };
93
94 static void ib_sa_add_one(struct ib_device *device);
95 static void ib_sa_remove_one(struct ib_device *device);
96
97 static struct ib_client sa_client = {
98         .name   = "sa",
99         .add    = ib_sa_add_one,
100         .remove = ib_sa_remove_one
101 };
102
103 static spinlock_t idr_lock;
104 static DEFINE_IDR(query_idr);
105
106 static spinlock_t tid_lock;
107 static u32 tid;
108
109 enum {
110         IB_SA_ATTR_CLASS_PORTINFO    = 0x01,
111         IB_SA_ATTR_NOTICE            = 0x02,
112         IB_SA_ATTR_INFORM_INFO       = 0x03,
113         IB_SA_ATTR_NODE_REC          = 0x11,
114         IB_SA_ATTR_PORT_INFO_REC     = 0x12,
115         IB_SA_ATTR_SL2VL_REC         = 0x13,
116         IB_SA_ATTR_SWITCH_REC        = 0x14,
117         IB_SA_ATTR_LINEAR_FDB_REC    = 0x15,
118         IB_SA_ATTR_RANDOM_FDB_REC    = 0x16,
119         IB_SA_ATTR_MCAST_FDB_REC     = 0x17,
120         IB_SA_ATTR_SM_INFO_REC       = 0x18,
121         IB_SA_ATTR_LINK_REC          = 0x20,
122         IB_SA_ATTR_GUID_INFO_REC     = 0x30,
123         IB_SA_ATTR_SERVICE_REC       = 0x31,
124         IB_SA_ATTR_PARTITION_REC     = 0x33,
125         IB_SA_ATTR_RANGE_REC         = 0x34,
126         IB_SA_ATTR_PATH_REC          = 0x35,
127         IB_SA_ATTR_VL_ARB_REC        = 0x36,
128         IB_SA_ATTR_MC_GROUP_REC      = 0x37,
129         IB_SA_ATTR_MC_MEMBER_REC     = 0x38,
130         IB_SA_ATTR_TRACE_REC         = 0x39,
131         IB_SA_ATTR_MULTI_PATH_REC    = 0x3a,
132         IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b
133 };
134
135 #define PATH_REC_FIELD(field) \
136         .struct_offset_bytes = offsetof(struct ib_sa_path_rec, field),          \
137         .struct_size_bytes   = sizeof ((struct ib_sa_path_rec *) 0)->field,     \
138         .field_name          = "sa_path_rec:" #field
139
140 static const struct ib_field path_rec_table[] = {
141         { RESERVED,
142           .offset_words = 0,
143           .offset_bits  = 0,
144           .size_bits    = 32 },
145         { RESERVED,
146           .offset_words = 1,
147           .offset_bits  = 0,
148           .size_bits    = 32 },
149         { PATH_REC_FIELD(dgid),
150           .offset_words = 2,
151           .offset_bits  = 0,
152           .size_bits    = 128 },
153         { PATH_REC_FIELD(sgid),
154           .offset_words = 6,
155           .offset_bits  = 0,
156           .size_bits    = 128 },
157         { PATH_REC_FIELD(dlid),
158           .offset_words = 10,
159           .offset_bits  = 0,
160           .size_bits    = 16 },
161         { PATH_REC_FIELD(slid),
162           .offset_words = 10,
163           .offset_bits  = 16,
164           .size_bits    = 16 },
165         { PATH_REC_FIELD(raw_traffic),
166           .offset_words = 11,
167           .offset_bits  = 0,
168           .size_bits    = 1 },
169         { RESERVED,
170           .offset_words = 11,
171           .offset_bits  = 1,
172           .size_bits    = 3 },
173         { PATH_REC_FIELD(flow_label),
174           .offset_words = 11,
175           .offset_bits  = 4,
176           .size_bits    = 20 },
177         { PATH_REC_FIELD(hop_limit),
178           .offset_words = 11,
179           .offset_bits  = 24,
180           .size_bits    = 8 },
181         { PATH_REC_FIELD(traffic_class),
182           .offset_words = 12,
183           .offset_bits  = 0,
184           .size_bits    = 8 },
185         { PATH_REC_FIELD(reversible),
186           .offset_words = 12,
187           .offset_bits  = 8,
188           .size_bits    = 1 },
189         { PATH_REC_FIELD(numb_path),
190           .offset_words = 12,
191           .offset_bits  = 9,
192           .size_bits    = 7 },
193         { PATH_REC_FIELD(pkey),
194           .offset_words = 12,
195           .offset_bits  = 16,
196           .size_bits    = 16 },
197         { RESERVED,
198           .offset_words = 13,
199           .offset_bits  = 0,
200           .size_bits    = 12 },
201         { PATH_REC_FIELD(sl),
202           .offset_words = 13,
203           .offset_bits  = 12,
204           .size_bits    = 4 },
205         { PATH_REC_FIELD(mtu_selector),
206           .offset_words = 13,
207           .offset_bits  = 16,
208           .size_bits    = 2 },
209         { PATH_REC_FIELD(mtu),
210           .offset_words = 13,
211           .offset_bits  = 18,
212           .size_bits    = 6 },
213         { PATH_REC_FIELD(rate_selector),
214           .offset_words = 13,
215           .offset_bits  = 24,
216           .size_bits    = 2 },
217         { PATH_REC_FIELD(rate),
218           .offset_words = 13,
219           .offset_bits  = 26,
220           .size_bits    = 6 },
221         { PATH_REC_FIELD(packet_life_time_selector),
222           .offset_words = 14,
223           .offset_bits  = 0,
224           .size_bits    = 2 },
225         { PATH_REC_FIELD(packet_life_time),
226           .offset_words = 14,
227           .offset_bits  = 2,
228           .size_bits    = 6 },
229         { PATH_REC_FIELD(preference),
230           .offset_words = 14,
231           .offset_bits  = 8,
232           .size_bits    = 8 },
233         { RESERVED,
234           .offset_words = 14,
235           .offset_bits  = 16,
236           .size_bits    = 48 },
237 };
238
239 #define MCMEMBER_REC_FIELD(field) \
240         .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field),      \
241         .struct_size_bytes   = sizeof ((struct ib_sa_mcmember_rec *) 0)->field, \
242         .field_name          = "sa_mcmember_rec:" #field
243
244 static const struct ib_field mcmember_rec_table[] = {
245         { MCMEMBER_REC_FIELD(mgid),
246           .offset_words = 0,
247           .offset_bits  = 0,
248           .size_bits    = 128 },
249         { MCMEMBER_REC_FIELD(port_gid),
250           .offset_words = 4,
251           .offset_bits  = 0,
252           .size_bits    = 128 },
253         { MCMEMBER_REC_FIELD(qkey),
254           .offset_words = 8,
255           .offset_bits  = 0,
256           .size_bits    = 32 },
257         { MCMEMBER_REC_FIELD(mlid),
258           .offset_words = 9,
259           .offset_bits  = 0,
260           .size_bits    = 16 },
261         { MCMEMBER_REC_FIELD(mtu_selector),
262           .offset_words = 9,
263           .offset_bits  = 16,
264           .size_bits    = 2 },
265         { MCMEMBER_REC_FIELD(mtu),
266           .offset_words = 9,
267           .offset_bits  = 18,
268           .size_bits    = 6 },
269         { MCMEMBER_REC_FIELD(traffic_class),
270           .offset_words = 9,
271           .offset_bits  = 24,
272           .size_bits    = 8 },
273         { MCMEMBER_REC_FIELD(pkey),
274           .offset_words = 10,
275           .offset_bits  = 0,
276           .size_bits    = 16 },
277         { MCMEMBER_REC_FIELD(rate_selector),
278           .offset_words = 10,
279           .offset_bits  = 16,
280           .size_bits    = 2 },
281         { MCMEMBER_REC_FIELD(rate),
282           .offset_words = 10,
283           .offset_bits  = 18,
284           .size_bits    = 6 },
285         { MCMEMBER_REC_FIELD(packet_life_time_selector),
286           .offset_words = 10,
287           .offset_bits  = 24,
288           .size_bits    = 2 },
289         { MCMEMBER_REC_FIELD(packet_life_time),
290           .offset_words = 10,
291           .offset_bits  = 26,
292           .size_bits    = 6 },
293         { MCMEMBER_REC_FIELD(sl),
294           .offset_words = 11,
295           .offset_bits  = 0,
296           .size_bits    = 4 },
297         { MCMEMBER_REC_FIELD(flow_label),
298           .offset_words = 11,
299           .offset_bits  = 4,
300           .size_bits    = 20 },
301         { MCMEMBER_REC_FIELD(hop_limit),
302           .offset_words = 11,
303           .offset_bits  = 24,
304           .size_bits    = 8 },
305         { MCMEMBER_REC_FIELD(scope),
306           .offset_words = 12,
307           .offset_bits  = 0,
308           .size_bits    = 4 },
309         { MCMEMBER_REC_FIELD(join_state),
310           .offset_words = 12,
311           .offset_bits  = 4,
312           .size_bits    = 4 },
313         { MCMEMBER_REC_FIELD(proxy_join),
314           .offset_words = 12,
315           .offset_bits  = 8,
316           .size_bits    = 1 },
317         { RESERVED,
318           .offset_words = 12,
319           .offset_bits  = 9,
320           .size_bits    = 23 },
321 };
322
323 static void free_sm_ah(struct kref *kref)
324 {
325         struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
326
327         ib_destroy_ah(sm_ah->ah);
328         kfree(sm_ah);
329 }
330
331 static void update_sm_ah(void *port_ptr)
332 {
333         struct ib_sa_port *port = port_ptr;
334         struct ib_sa_sm_ah *new_ah, *old_ah;
335         struct ib_port_attr port_attr;
336         struct ib_ah_attr   ah_attr;
337
338         if (ib_query_port(port->agent->device, port->port_num, &port_attr)) {
339                 printk(KERN_WARNING "Couldn't query port\n");
340                 return;
341         }
342
343         new_ah = kmalloc(sizeof *new_ah, GFP_KERNEL);
344         if (!new_ah) {
345                 printk(KERN_WARNING "Couldn't allocate new SM AH\n");
346                 return;
347         }
348
349         kref_init(&new_ah->ref);
350
351         memset(&ah_attr, 0, sizeof ah_attr);
352         ah_attr.dlid     = port_attr.sm_lid;
353         ah_attr.sl       = port_attr.sm_sl;
354         ah_attr.port_num = port->port_num;
355
356         new_ah->ah = ib_create_ah(port->agent->qp->pd, &ah_attr);
357         if (IS_ERR(new_ah->ah)) {
358                 printk(KERN_WARNING "Couldn't create new SM AH\n");
359                 kfree(new_ah);
360                 return;
361         }
362
363         spin_lock_irq(&port->ah_lock);
364         old_ah = port->sm_ah;
365         port->sm_ah = new_ah;
366         spin_unlock_irq(&port->ah_lock);
367
368         if (old_ah)
369                 kref_put(&old_ah->ref, free_sm_ah);
370 }
371
372 static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event)
373 {
374         if (event->event == IB_EVENT_PORT_ERR    ||
375             event->event == IB_EVENT_PORT_ACTIVE ||
376             event->event == IB_EVENT_LID_CHANGE  ||
377             event->event == IB_EVENT_PKEY_CHANGE ||
378             event->event == IB_EVENT_SM_CHANGE) {
379                 struct ib_sa_device *sa_dev =
380                         ib_get_client_data(event->device, &sa_client);
381
382                 schedule_work(&sa_dev->port[event->element.port_num -
383                                             sa_dev->start_port].update_task);
384         }
385 }
386
387 /**
388  * ib_sa_cancel_query - try to cancel an SA query
389  * @id:ID of query to cancel
390  * @query:query pointer to cancel
391  *
392  * Try to cancel an SA query.  If the id and query don't match up or
393  * the query has already completed, nothing is done.  Otherwise the
394  * query is canceled and will complete with a status of -EINTR.
395  */
396 void ib_sa_cancel_query(int id, struct ib_sa_query *query)
397 {
398         unsigned long flags;
399         struct ib_mad_agent *agent;
400
401         spin_lock_irqsave(&idr_lock, flags);
402         if (idr_find(&query_idr, id) != query) {
403                 spin_unlock_irqrestore(&idr_lock, flags);
404                 return;
405         }
406         agent = query->port->agent;
407         spin_unlock_irqrestore(&idr_lock, flags);
408
409         ib_cancel_mad(agent, id);
410 }
411 EXPORT_SYMBOL(ib_sa_cancel_query);
412
413 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
414 {
415         unsigned long flags;
416
417         memset(mad, 0, sizeof *mad);
418
419         mad->mad_hdr.base_version  = IB_MGMT_BASE_VERSION;
420         mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_SUBN_ADM;
421         mad->mad_hdr.class_version = IB_SA_CLASS_VERSION;
422
423         spin_lock_irqsave(&tid_lock, flags);
424         mad->mad_hdr.tid           =
425                 cpu_to_be64(((u64) agent->hi_tid) << 32 | tid++);
426         spin_unlock_irqrestore(&tid_lock, flags);
427 }
428
429 static int send_mad(struct ib_sa_query *query, int timeout_ms)
430 {
431         struct ib_sa_port *port = query->port;
432         unsigned long flags;
433         int ret;
434         struct ib_sge      gather_list;
435         struct ib_send_wr *bad_wr, wr = {
436                 .opcode      = IB_WR_SEND,
437                 .sg_list     = &gather_list,
438                 .num_sge     = 1,
439                 .send_flags  = IB_SEND_SIGNALED,
440                 .wr          = {
441                          .ud = {
442                                  .mad_hdr     = &query->mad->mad_hdr,
443                                  .remote_qpn  = 1,
444                                  .remote_qkey = IB_QP1_QKEY,
445                                  .timeout_ms  = timeout_ms,
446                                  .retries     = 0
447                          }
448                  }
449         };
450
451 retry:
452         if (!idr_pre_get(&query_idr, GFP_ATOMIC))
453                 return -ENOMEM;
454         spin_lock_irqsave(&idr_lock, flags);
455         ret = idr_get_new(&query_idr, query, &query->id);
456         spin_unlock_irqrestore(&idr_lock, flags);
457         if (ret == -EAGAIN)
458                 goto retry;
459         if (ret)
460                 return ret;
461
462         wr.wr_id = query->id;
463
464         spin_lock_irqsave(&port->ah_lock, flags);
465         kref_get(&port->sm_ah->ref);
466         query->sm_ah = port->sm_ah;
467         wr.wr.ud.ah  = port->sm_ah->ah;
468         spin_unlock_irqrestore(&port->ah_lock, flags);
469
470         gather_list.addr   = dma_map_single(port->agent->device->dma_device,
471                                             query->mad,
472                                             sizeof (struct ib_sa_mad),
473                                             DMA_TO_DEVICE);
474         gather_list.length = sizeof (struct ib_sa_mad);
475         gather_list.lkey   = port->agent->mr->lkey;
476         pci_unmap_addr_set(query, mapping, gather_list.addr);
477
478         ret = ib_post_send_mad(port->agent, &wr, &bad_wr);
479         if (ret) {
480                 dma_unmap_single(port->agent->device->dma_device,
481                                  pci_unmap_addr(query, mapping),
482                                  sizeof (struct ib_sa_mad),
483                                  DMA_TO_DEVICE);
484                 kref_put(&query->sm_ah->ref, free_sm_ah);
485                 spin_lock_irqsave(&idr_lock, flags);
486                 idr_remove(&query_idr, query->id);
487                 spin_unlock_irqrestore(&idr_lock, flags);
488         }
489
490         /*
491          * It's not safe to dereference query any more, because the
492          * send may already have completed and freed the query in
493          * another context.  So use wr.wr_id, which has a copy of the
494          * query's id.
495          */
496         return ret ? ret : wr.wr_id;
497 }
498
499 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
500                                     int status,
501                                     struct ib_sa_mad *mad)
502 {
503         struct ib_sa_path_query *query =
504                 container_of(sa_query, struct ib_sa_path_query, sa_query);
505
506         if (mad) {
507                 struct ib_sa_path_rec rec;
508
509                 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
510                           mad->data, &rec);
511                 query->callback(status, &rec, query->context);
512         } else
513                 query->callback(status, NULL, query->context);
514 }
515
516 static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
517 {
518         kfree(sa_query->mad);
519         kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
520 }
521
522 /**
523  * ib_sa_path_rec_get - Start a Path get query
524  * @device:device to send query on
525  * @port_num: port number to send query on
526  * @rec:Path Record to send in query
527  * @comp_mask:component mask to send in query
528  * @timeout_ms:time to wait for response
529  * @gfp_mask:GFP mask to use for internal allocations
530  * @callback:function called when query completes, times out or is
531  * canceled
532  * @context:opaque user context passed to callback
533  * @sa_query:query context, used to cancel query
534  *
535  * Send a Path Record Get query to the SA to look up a path.  The
536  * callback function will be called when the query completes (or
537  * fails); status is 0 for a successful response, -EINTR if the query
538  * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
539  * occurred sending the query.  The resp parameter of the callback is
540  * only valid if status is 0.
541  *
542  * If the return value of ib_sa_path_rec_get() is negative, it is an
543  * error code.  Otherwise it is a query ID that can be used to cancel
544  * the query.
545  */
546 int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
547                        struct ib_sa_path_rec *rec,
548                        ib_sa_comp_mask comp_mask,
549                        int timeout_ms, int gfp_mask,
550                        void (*callback)(int status,
551                                         struct ib_sa_path_rec *resp,
552                                         void *context),
553                        void *context,
554                        struct ib_sa_query **sa_query)
555 {
556         struct ib_sa_path_query *query;
557         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
558         struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
559         struct ib_mad_agent *agent  = port->agent;
560         int ret;
561
562         query = kmalloc(sizeof *query, gfp_mask);
563         if (!query)
564                 return -ENOMEM;
565         query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
566         if (!query->sa_query.mad) {
567                 kfree(query);
568                 return -ENOMEM;
569         }
570
571         query->callback = callback;
572         query->context  = context;
573
574         init_mad(query->sa_query.mad, agent);
575
576         query->sa_query.callback              = callback ? ib_sa_path_rec_callback : NULL;
577         query->sa_query.release               = ib_sa_path_rec_release;
578         query->sa_query.port                  = port;
579         query->sa_query.mad->mad_hdr.method   = IB_MGMT_METHOD_GET;
580         query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_PATH_REC);
581         query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
582
583         ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
584                 rec, query->sa_query.mad->data);
585
586         *sa_query = &query->sa_query;
587
588         ret = send_mad(&query->sa_query, timeout_ms);
589         if (ret < 0) {
590                 *sa_query = NULL;
591                 kfree(query->sa_query.mad);
592                 kfree(query);
593         }
594
595         return ret;
596 }
597 EXPORT_SYMBOL(ib_sa_path_rec_get);
598
599 static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
600                                         int status,
601                                         struct ib_sa_mad *mad)
602 {
603         struct ib_sa_mcmember_query *query =
604                 container_of(sa_query, struct ib_sa_mcmember_query, sa_query);
605
606         if (mad) {
607                 struct ib_sa_mcmember_rec rec;
608
609                 ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
610                           mad->data, &rec);
611                 query->callback(status, &rec, query->context);
612         } else
613                 query->callback(status, NULL, query->context);
614 }
615
616 static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
617 {
618         kfree(sa_query->mad);
619         kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
620 }
621
622 int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
623                              u8 method,
624                              struct ib_sa_mcmember_rec *rec,
625                              ib_sa_comp_mask comp_mask,
626                              int timeout_ms, int gfp_mask,
627                              void (*callback)(int status,
628                                               struct ib_sa_mcmember_rec *resp,
629                                               void *context),
630                              void *context,
631                              struct ib_sa_query **sa_query)
632 {
633         struct ib_sa_mcmember_query *query;
634         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
635         struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
636         struct ib_mad_agent *agent  = port->agent;
637         int ret;
638
639         query = kmalloc(sizeof *query, gfp_mask);
640         if (!query)
641                 return -ENOMEM;
642         query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
643         if (!query->sa_query.mad) {
644                 kfree(query);
645                 return -ENOMEM;
646         }
647
648         query->callback = callback;
649         query->context  = context;
650
651         init_mad(query->sa_query.mad, agent);
652
653         query->sa_query.callback              = callback ? ib_sa_mcmember_rec_callback : NULL;
654         query->sa_query.release               = ib_sa_mcmember_rec_release;
655         query->sa_query.port                  = port;
656         query->sa_query.mad->mad_hdr.method   = method;
657         query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
658         query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
659
660         ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
661                 rec, query->sa_query.mad->data);
662
663         *sa_query = &query->sa_query;
664
665         ret = send_mad(&query->sa_query, timeout_ms);
666         if (ret < 0) {
667                 *sa_query = NULL;
668                 kfree(query->sa_query.mad);
669                 kfree(query);
670         }
671
672         return ret;
673 }
674 EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
675
676 static void send_handler(struct ib_mad_agent *agent,
677                          struct ib_mad_send_wc *mad_send_wc)
678 {
679         struct ib_sa_query *query;
680         unsigned long flags;
681
682         spin_lock_irqsave(&idr_lock, flags);
683         query = idr_find(&query_idr, mad_send_wc->wr_id);
684         spin_unlock_irqrestore(&idr_lock, flags);
685
686         if (!query)
687                 return;
688
689         if (query->callback)
690                 switch (mad_send_wc->status) {
691                 case IB_WC_SUCCESS:
692                         /* No callback -- already got recv */
693                         break;
694                 case IB_WC_RESP_TIMEOUT_ERR:
695                         query->callback(query, -ETIMEDOUT, NULL);
696                         break;
697                 case IB_WC_WR_FLUSH_ERR:
698                         query->callback(query, -EINTR, NULL);
699                         break;
700                 default:
701                         query->callback(query, -EIO, NULL);
702                         break;
703                 }
704
705         dma_unmap_single(agent->device->dma_device,
706                          pci_unmap_addr(query, mapping),
707                          sizeof (struct ib_sa_mad),
708                          DMA_TO_DEVICE);
709         kref_put(&query->sm_ah->ref, free_sm_ah);
710
711         query->release(query);
712
713         spin_lock_irqsave(&idr_lock, flags);
714         idr_remove(&query_idr, mad_send_wc->wr_id);
715         spin_unlock_irqrestore(&idr_lock, flags);
716 }
717
718 static void recv_handler(struct ib_mad_agent *mad_agent,
719                          struct ib_mad_recv_wc *mad_recv_wc)
720 {
721         struct ib_sa_query *query;
722         unsigned long flags;
723
724         spin_lock_irqsave(&idr_lock, flags);
725         query = idr_find(&query_idr, mad_recv_wc->wc->wr_id);
726         spin_unlock_irqrestore(&idr_lock, flags);
727
728         if (query && query->callback) {
729                 if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
730                         query->callback(query,
731                                         mad_recv_wc->recv_buf.mad->mad_hdr.status ?
732                                         -EINVAL : 0,
733                                         (struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);
734                 else
735                         query->callback(query, -EIO, NULL);
736         }
737
738         ib_free_recv_mad(mad_recv_wc);
739 }
740
741 static void ib_sa_add_one(struct ib_device *device)
742 {
743         struct ib_sa_device *sa_dev;
744         int s, e, i;
745
746         if (device->node_type == IB_NODE_SWITCH)
747                 s = e = 0;
748         else {
749                 s = 1;
750                 e = device->phys_port_cnt;
751         }
752
753         sa_dev = kmalloc(sizeof *sa_dev +
754                          (e - s + 1) * sizeof (struct ib_sa_port),
755                          GFP_KERNEL);
756         if (!sa_dev)
757                 return;
758
759         sa_dev->start_port = s;
760         sa_dev->end_port   = e;
761
762         for (i = 0; i <= e - s; ++i) {
763                 sa_dev->port[i].sm_ah    = NULL;
764                 sa_dev->port[i].port_num = i + s;
765                 spin_lock_init(&sa_dev->port[i].ah_lock);
766
767                 sa_dev->port[i].agent =
768                         ib_register_mad_agent(device, i + s, IB_QPT_GSI,
769                                               NULL, 0, send_handler,
770                                               recv_handler, sa_dev);
771                 if (IS_ERR(sa_dev->port[i].agent))
772                         goto err;
773
774                 INIT_WORK(&sa_dev->port[i].update_task,
775                           update_sm_ah, &sa_dev->port[i]);
776         }
777
778         ib_set_client_data(device, &sa_client, sa_dev);
779
780         /*
781          * We register our event handler after everything is set up,
782          * and then update our cached info after the event handler is
783          * registered to avoid any problems if a port changes state
784          * during our initialization.
785          */
786
787         INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);
788         if (ib_register_event_handler(&sa_dev->event_handler))
789                 goto err;
790
791         for (i = 0; i <= e - s; ++i)
792                 update_sm_ah(&sa_dev->port[i]);
793
794         return;
795
796 err:
797         while (--i >= 0)
798                 ib_unregister_mad_agent(sa_dev->port[i].agent);
799
800         kfree(sa_dev);
801
802         return;
803 }
804
805 static void ib_sa_remove_one(struct ib_device *device)
806 {
807         struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
808         int i;
809
810         if (!sa_dev)
811                 return;
812
813         ib_unregister_event_handler(&sa_dev->event_handler);
814
815         for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
816                 ib_unregister_mad_agent(sa_dev->port[i].agent);
817                 kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
818         }
819
820         kfree(sa_dev);
821 }
822
823 static int __init ib_sa_init(void)
824 {
825         int ret;
826
827         spin_lock_init(&idr_lock);
828         spin_lock_init(&tid_lock);
829
830         get_random_bytes(&tid, sizeof tid);
831
832         ret = ib_register_client(&sa_client);
833         if (ret)
834                 printk(KERN_ERR "Couldn't register ib_sa client\n");
835
836         return ret;
837 }
838
839 static void __exit ib_sa_cleanup(void)
840 {
841         ib_unregister_client(&sa_client);
842 }
843
844 module_init(ib_sa_init);
845 module_exit(ib_sa_cleanup);