sa_query.c revision 256281
1/*
2 * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3 * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
4 * Copyright (c) 2006 Intel Corporation.  All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
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/dma-mapping.h>
42#include <linux/kref.h>
43#include <linux/idr.h>
44#include <linux/workqueue.h>
45
46#include <rdma/ib_pack.h>
47#include <rdma/ib_cache.h>
48#include "sa.h"
49
50MODULE_AUTHOR("Roland Dreier");
51MODULE_DESCRIPTION("InfiniBand subnet administration query support");
52MODULE_LICENSE("Dual BSD/GPL");
53
54struct ib_sa_sm_ah {
55	struct ib_ah        *ah;
56	struct kref          ref;
57	u16		     pkey_index;
58	u8		     src_path_mask;
59};
60
61struct ib_sa_port {
62	struct ib_mad_agent *agent;
63	struct ib_mad_agent *notice_agent;
64	struct ib_sa_sm_ah  *sm_ah;
65	struct work_struct   update_task;
66	spinlock_t           ah_lock;
67	u8                   port_num;
68	struct ib_device    *device;
69};
70
71struct ib_sa_device {
72	int                     start_port, end_port;
73	struct ib_event_handler event_handler;
74	struct ib_sa_port port[0];
75};
76
77struct ib_sa_query {
78	void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
79	void (*release)(struct ib_sa_query *);
80	struct ib_sa_client    *client;
81	struct ib_sa_port      *port;
82	struct ib_mad_send_buf *mad_buf;
83	struct ib_sa_sm_ah     *sm_ah;
84	int			id;
85};
86
87struct ib_sa_service_query {
88	void (*callback)(int, struct ib_sa_service_rec *, void *);
89	void *context;
90	struct ib_sa_query sa_query;
91};
92
93struct ib_sa_path_query {
94	void (*callback)(int, struct ib_sa_path_rec *, void *);
95	void *context;
96	struct ib_sa_query sa_query;
97};
98
99struct ib_sa_mcmember_query {
100	void (*callback)(int, struct ib_sa_mcmember_rec *, void *);
101	void *context;
102	struct ib_sa_query sa_query;
103};
104
105struct ib_sa_inform_query {
106	void (*callback)(int, struct ib_sa_inform *, void *);
107	void *context;
108	struct ib_sa_query sa_query;
109};
110
111static void ib_sa_add_one(struct ib_device *device);
112static void ib_sa_remove_one(struct ib_device *device);
113
114static struct ib_client sa_client = {
115	.name   = "sa",
116	.add    = ib_sa_add_one,
117	.remove = ib_sa_remove_one
118};
119
120static spinlock_t idr_lock;
121static DEFINE_IDR(query_idr);
122
123static spinlock_t tid_lock;
124static u32 tid;
125
126#define PATH_REC_FIELD(field) \
127	.struct_offset_bytes = offsetof(struct ib_sa_path_rec, field),		\
128	.struct_size_bytes   = sizeof ((struct ib_sa_path_rec *) 0)->field,	\
129	.field_name          = "sa_path_rec:" #field
130
131static const struct ib_field path_rec_table[] = {
132	{ PATH_REC_FIELD(service_id),
133	  .offset_words = 0,
134	  .offset_bits  = 0,
135	  .size_bits    = 64 },
136	{ PATH_REC_FIELD(dgid),
137	  .offset_words = 2,
138	  .offset_bits  = 0,
139	  .size_bits    = 128 },
140	{ PATH_REC_FIELD(sgid),
141	  .offset_words = 6,
142	  .offset_bits  = 0,
143	  .size_bits    = 128 },
144	{ PATH_REC_FIELD(dlid),
145	  .offset_words = 10,
146	  .offset_bits  = 0,
147	  .size_bits    = 16 },
148	{ PATH_REC_FIELD(slid),
149	  .offset_words = 10,
150	  .offset_bits  = 16,
151	  .size_bits    = 16 },
152	{ PATH_REC_FIELD(raw_traffic),
153	  .offset_words = 11,
154	  .offset_bits  = 0,
155	  .size_bits    = 1 },
156	{ RESERVED,
157	  .offset_words = 11,
158	  .offset_bits  = 1,
159	  .size_bits    = 3 },
160	{ PATH_REC_FIELD(flow_label),
161	  .offset_words = 11,
162	  .offset_bits  = 4,
163	  .size_bits    = 20 },
164	{ PATH_REC_FIELD(hop_limit),
165	  .offset_words = 11,
166	  .offset_bits  = 24,
167	  .size_bits    = 8 },
168	{ PATH_REC_FIELD(traffic_class),
169	  .offset_words = 12,
170	  .offset_bits  = 0,
171	  .size_bits    = 8 },
172	{ PATH_REC_FIELD(reversible),
173	  .offset_words = 12,
174	  .offset_bits  = 8,
175	  .size_bits    = 1 },
176	{ PATH_REC_FIELD(numb_path),
177	  .offset_words = 12,
178	  .offset_bits  = 9,
179	  .size_bits    = 7 },
180	{ PATH_REC_FIELD(pkey),
181	  .offset_words = 12,
182	  .offset_bits  = 16,
183	  .size_bits    = 16 },
184	{ PATH_REC_FIELD(qos_class),
185	  .offset_words = 13,
186	  .offset_bits  = 0,
187	  .size_bits    = 12 },
188	{ PATH_REC_FIELD(sl),
189	  .offset_words = 13,
190	  .offset_bits  = 12,
191	  .size_bits    = 4 },
192	{ PATH_REC_FIELD(mtu_selector),
193	  .offset_words = 13,
194	  .offset_bits  = 16,
195	  .size_bits    = 2 },
196	{ PATH_REC_FIELD(mtu),
197	  .offset_words = 13,
198	  .offset_bits  = 18,
199	  .size_bits    = 6 },
200	{ PATH_REC_FIELD(rate_selector),
201	  .offset_words = 13,
202	  .offset_bits  = 24,
203	  .size_bits    = 2 },
204	{ PATH_REC_FIELD(rate),
205	  .offset_words = 13,
206	  .offset_bits  = 26,
207	  .size_bits    = 6 },
208	{ PATH_REC_FIELD(packet_life_time_selector),
209	  .offset_words = 14,
210	  .offset_bits  = 0,
211	  .size_bits    = 2 },
212	{ PATH_REC_FIELD(packet_life_time),
213	  .offset_words = 14,
214	  .offset_bits  = 2,
215	  .size_bits    = 6 },
216	{ PATH_REC_FIELD(preference),
217	  .offset_words = 14,
218	  .offset_bits  = 8,
219	  .size_bits    = 8 },
220	{ RESERVED,
221	  .offset_words = 14,
222	  .offset_bits  = 16,
223	  .size_bits    = 48 },
224};
225
226#define MCMEMBER_REC_FIELD(field) \
227	.struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field),	\
228	.struct_size_bytes   = sizeof ((struct ib_sa_mcmember_rec *) 0)->field,	\
229	.field_name          = "sa_mcmember_rec:" #field
230
231static const struct ib_field mcmember_rec_table[] = {
232	{ MCMEMBER_REC_FIELD(mgid),
233	  .offset_words = 0,
234	  .offset_bits  = 0,
235	  .size_bits    = 128 },
236	{ MCMEMBER_REC_FIELD(port_gid),
237	  .offset_words = 4,
238	  .offset_bits  = 0,
239	  .size_bits    = 128 },
240	{ MCMEMBER_REC_FIELD(qkey),
241	  .offset_words = 8,
242	  .offset_bits  = 0,
243	  .size_bits    = 32 },
244	{ MCMEMBER_REC_FIELD(mlid),
245	  .offset_words = 9,
246	  .offset_bits  = 0,
247	  .size_bits    = 16 },
248	{ MCMEMBER_REC_FIELD(mtu_selector),
249	  .offset_words = 9,
250	  .offset_bits  = 16,
251	  .size_bits    = 2 },
252	{ MCMEMBER_REC_FIELD(mtu),
253	  .offset_words = 9,
254	  .offset_bits  = 18,
255	  .size_bits    = 6 },
256	{ MCMEMBER_REC_FIELD(traffic_class),
257	  .offset_words = 9,
258	  .offset_bits  = 24,
259	  .size_bits    = 8 },
260	{ MCMEMBER_REC_FIELD(pkey),
261	  .offset_words = 10,
262	  .offset_bits  = 0,
263	  .size_bits    = 16 },
264	{ MCMEMBER_REC_FIELD(rate_selector),
265	  .offset_words = 10,
266	  .offset_bits  = 16,
267	  .size_bits    = 2 },
268	{ MCMEMBER_REC_FIELD(rate),
269	  .offset_words = 10,
270	  .offset_bits  = 18,
271	  .size_bits    = 6 },
272	{ MCMEMBER_REC_FIELD(packet_life_time_selector),
273	  .offset_words = 10,
274	  .offset_bits  = 24,
275	  .size_bits    = 2 },
276	{ MCMEMBER_REC_FIELD(packet_life_time),
277	  .offset_words = 10,
278	  .offset_bits  = 26,
279	  .size_bits    = 6 },
280	{ MCMEMBER_REC_FIELD(sl),
281	  .offset_words = 11,
282	  .offset_bits  = 0,
283	  .size_bits    = 4 },
284	{ MCMEMBER_REC_FIELD(flow_label),
285	  .offset_words = 11,
286	  .offset_bits  = 4,
287	  .size_bits    = 20 },
288	{ MCMEMBER_REC_FIELD(hop_limit),
289	  .offset_words = 11,
290	  .offset_bits  = 24,
291	  .size_bits    = 8 },
292	{ MCMEMBER_REC_FIELD(scope),
293	  .offset_words = 12,
294	  .offset_bits  = 0,
295	  .size_bits    = 4 },
296	{ MCMEMBER_REC_FIELD(join_state),
297	  .offset_words = 12,
298	  .offset_bits  = 4,
299	  .size_bits    = 4 },
300	{ MCMEMBER_REC_FIELD(proxy_join),
301	  .offset_words = 12,
302	  .offset_bits  = 8,
303	  .size_bits    = 1 },
304	{ RESERVED,
305	  .offset_words = 12,
306	  .offset_bits  = 9,
307	  .size_bits    = 23 },
308};
309
310#define SERVICE_REC_FIELD(field) \
311	.struct_offset_bytes = offsetof(struct ib_sa_service_rec, field),	\
312	.struct_size_bytes   = sizeof ((struct ib_sa_service_rec *) 0)->field,	\
313	.field_name          = "sa_service_rec:" #field
314
315static const struct ib_field service_rec_table[] = {
316	{ SERVICE_REC_FIELD(id),
317	  .offset_words = 0,
318	  .offset_bits  = 0,
319	  .size_bits    = 64 },
320	{ SERVICE_REC_FIELD(gid),
321	  .offset_words = 2,
322	  .offset_bits  = 0,
323	  .size_bits    = 128 },
324	{ SERVICE_REC_FIELD(pkey),
325	  .offset_words = 6,
326	  .offset_bits  = 0,
327	  .size_bits    = 16 },
328	{ SERVICE_REC_FIELD(lease),
329	  .offset_words = 7,
330	  .offset_bits  = 0,
331	  .size_bits    = 32 },
332	{ SERVICE_REC_FIELD(key),
333	  .offset_words = 8,
334	  .offset_bits  = 0,
335	  .size_bits    = 128 },
336	{ SERVICE_REC_FIELD(name),
337	  .offset_words = 12,
338	  .offset_bits  = 0,
339	  .size_bits    = 64*8 },
340	{ SERVICE_REC_FIELD(data8),
341	  .offset_words = 28,
342	  .offset_bits  = 0,
343	  .size_bits    = 16*8 },
344	{ SERVICE_REC_FIELD(data16),
345	  .offset_words = 32,
346	  .offset_bits  = 0,
347	  .size_bits    = 8*16 },
348	{ SERVICE_REC_FIELD(data32),
349	  .offset_words = 36,
350	  .offset_bits  = 0,
351	  .size_bits    = 4*32 },
352	{ SERVICE_REC_FIELD(data64),
353	  .offset_words = 40,
354	  .offset_bits  = 0,
355	  .size_bits    = 2*64 },
356};
357
358#define INFORM_FIELD(field) \
359	.struct_offset_bytes = offsetof(struct ib_sa_inform, field), \
360	.struct_size_bytes   = sizeof ((struct ib_sa_inform *) 0)->field, \
361	.field_name          = "sa_inform:" #field
362
363static const struct ib_field inform_table[] = {
364	{ INFORM_FIELD(gid),
365	  .offset_words = 0,
366	  .offset_bits  = 0,
367	  .size_bits    = 128 },
368	{ INFORM_FIELD(lid_range_begin),
369	  .offset_words = 4,
370	  .offset_bits  = 0,
371	  .size_bits    = 16 },
372	{ INFORM_FIELD(lid_range_end),
373	  .offset_words = 4,
374	  .offset_bits  = 16,
375	  .size_bits    = 16 },
376	{ RESERVED,
377	  .offset_words = 5,
378	  .offset_bits  = 0,
379	  .size_bits    = 16 },
380	{ INFORM_FIELD(is_generic),
381	  .offset_words = 5,
382	  .offset_bits  = 16,
383	  .size_bits    = 8 },
384	{ INFORM_FIELD(subscribe),
385	  .offset_words = 5,
386	  .offset_bits  = 24,
387	  .size_bits    = 8 },
388	{ INFORM_FIELD(type),
389	  .offset_words = 6,
390	  .offset_bits  = 0,
391	  .size_bits    = 16 },
392	{ INFORM_FIELD(trap.generic.trap_num),
393	  .offset_words = 6,
394	  .offset_bits  = 16,
395	  .size_bits    = 16 },
396	{ INFORM_FIELD(trap.generic.qpn),
397	  .offset_words = 7,
398	  .offset_bits  = 0,
399	  .size_bits    = 24 },
400	{ RESERVED,
401	  .offset_words = 7,
402	  .offset_bits  = 24,
403	  .size_bits    = 3 },
404	{ INFORM_FIELD(trap.generic.resp_time),
405	  .offset_words = 7,
406	  .offset_bits  = 27,
407	  .size_bits    = 5 },
408	{ RESERVED,
409	  .offset_words = 8,
410	  .offset_bits  = 0,
411	  .size_bits    = 8 },
412	{ INFORM_FIELD(trap.generic.producer_type),
413	  .offset_words = 8,
414	  .offset_bits  = 8,
415	  .size_bits    = 24 },
416};
417
418#define NOTICE_FIELD(field) \
419	.struct_offset_bytes = offsetof(struct ib_sa_notice, field), \
420	.struct_size_bytes   = sizeof ((struct ib_sa_notice *) 0)->field, \
421	.field_name          = "sa_notice:" #field
422
423static const struct ib_field notice_table[] = {
424	{ NOTICE_FIELD(is_generic),
425	  .offset_words = 0,
426	  .offset_bits  = 0,
427	  .size_bits    = 1 },
428	{ NOTICE_FIELD(type),
429	  .offset_words = 0,
430	  .offset_bits  = 1,
431	  .size_bits    = 7 },
432	{ NOTICE_FIELD(trap.generic.producer_type),
433	  .offset_words = 0,
434	  .offset_bits  = 8,
435	  .size_bits    = 24 },
436	{ NOTICE_FIELD(trap.generic.trap_num),
437	  .offset_words = 1,
438	  .offset_bits  = 0,
439	  .size_bits    = 16 },
440	{ NOTICE_FIELD(issuer_lid),
441	  .offset_words = 1,
442	  .offset_bits  = 16,
443	  .size_bits    = 16 },
444	{ NOTICE_FIELD(notice_toggle),
445	  .offset_words = 2,
446	  .offset_bits  = 0,
447	  .size_bits    = 1 },
448	{ NOTICE_FIELD(notice_count),
449	  .offset_words = 2,
450	  .offset_bits  = 1,
451	  .size_bits    = 15 },
452	{ NOTICE_FIELD(data_details),
453	  .offset_words = 2,
454	  .offset_bits  = 16,
455	  .size_bits    = 432 },
456	{ NOTICE_FIELD(issuer_gid),
457	  .offset_words = 16,
458	  .offset_bits  = 0,
459	  .size_bits    = 128 },
460};
461
462int ib_sa_check_selector(ib_sa_comp_mask comp_mask,
463			 ib_sa_comp_mask selector_mask,
464			 ib_sa_comp_mask value_mask,
465			 u8 selector, u8 src_value, u8 dst_value)
466{
467	int err;
468
469	if (!(comp_mask & selector_mask) || !(comp_mask & value_mask))
470		return 0;
471
472	switch (selector) {
473	case IB_SA_GT:
474		err = (src_value <= dst_value);
475		break;
476	case IB_SA_LT:
477		err = (src_value >= dst_value);
478		break;
479	case IB_SA_EQ:
480		err = (src_value != dst_value);
481		break;
482	default:
483		err = 0;
484		break;
485	}
486
487	return err;
488}
489
490int ib_sa_pack_attr(void *dst, void *src, int attr_id)
491{
492	switch (attr_id) {
493	case IB_SA_ATTR_PATH_REC:
494		ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), src, dst);
495		break;
496	default:
497		return -EINVAL;
498	}
499	return 0;
500}
501
502int ib_sa_unpack_attr(void *dst, void *src, int attr_id)
503{
504	switch (attr_id) {
505	case IB_SA_ATTR_PATH_REC:
506		ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), src, dst);
507		break;
508	default:
509		return -EINVAL;
510	}
511	return 0;
512}
513
514static void free_sm_ah(struct kref *kref)
515{
516	struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
517
518	ib_destroy_ah(sm_ah->ah);
519	kfree(sm_ah);
520}
521
522static void update_sm_ah(struct work_struct *work)
523{
524	struct ib_sa_port *port =
525		container_of(work, struct ib_sa_port, update_task);
526	struct ib_sa_sm_ah *new_ah;
527	struct ib_port_attr port_attr;
528	struct ib_ah_attr   ah_attr;
529
530	if (ib_query_port(port->agent->device, port->port_num, &port_attr)) {
531		printk(KERN_WARNING "Couldn't query port\n");
532		return;
533	}
534
535	new_ah = kmalloc(sizeof *new_ah, GFP_KERNEL);
536	if (!new_ah) {
537		printk(KERN_WARNING "Couldn't allocate new SM AH\n");
538		return;
539	}
540
541	kref_init(&new_ah->ref);
542	new_ah->src_path_mask = (1 << port_attr.lmc) - 1;
543
544	new_ah->pkey_index = 0;
545	if (ib_find_pkey(port->agent->device, port->port_num,
546			 IB_DEFAULT_PKEY_FULL, &new_ah->pkey_index))
547		printk(KERN_ERR "Couldn't find index for default PKey\n");
548
549	memset(&ah_attr, 0, sizeof ah_attr);
550	ah_attr.dlid     = port_attr.sm_lid;
551	ah_attr.sl       = port_attr.sm_sl;
552	ah_attr.port_num = port->port_num;
553
554	new_ah->ah = ib_create_ah(port->agent->qp->pd, &ah_attr);
555	if (IS_ERR(new_ah->ah)) {
556		printk(KERN_WARNING "Couldn't create new SM AH\n");
557		kfree(new_ah);
558		return;
559	}
560
561	spin_lock_irq(&port->ah_lock);
562	if (port->sm_ah)
563		kref_put(&port->sm_ah->ref, free_sm_ah);
564	port->sm_ah = new_ah;
565	spin_unlock_irq(&port->ah_lock);
566
567}
568
569static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event)
570{
571	if (event->event == IB_EVENT_PORT_ERR    ||
572	    event->event == IB_EVENT_PORT_ACTIVE ||
573	    event->event == IB_EVENT_LID_CHANGE  ||
574	    event->event == IB_EVENT_PKEY_CHANGE ||
575	    event->event == IB_EVENT_SM_CHANGE   ||
576	    event->event == IB_EVENT_CLIENT_REREGISTER) {
577		unsigned long flags;
578		struct ib_sa_device *sa_dev =
579			container_of(handler, typeof(*sa_dev), event_handler);
580		struct ib_sa_port *port =
581			&sa_dev->port[event->element.port_num - sa_dev->start_port];
582
583		if (rdma_port_get_link_layer(handler->device, port->port_num) != IB_LINK_LAYER_INFINIBAND)
584			return;
585
586		spin_lock_irqsave(&port->ah_lock, flags);
587		if (port->sm_ah)
588			kref_put(&port->sm_ah->ref, free_sm_ah);
589		port->sm_ah = NULL;
590		spin_unlock_irqrestore(&port->ah_lock, flags);
591
592		schedule_work(&sa_dev->port[event->element.port_num -
593					    sa_dev->start_port].update_task);
594	}
595}
596
597void ib_sa_register_client(struct ib_sa_client *client)
598{
599	atomic_set(&client->users, 1);
600	init_completion(&client->comp);
601}
602EXPORT_SYMBOL(ib_sa_register_client);
603
604void ib_sa_unregister_client(struct ib_sa_client *client)
605{
606	ib_sa_client_put(client);
607	wait_for_completion(&client->comp);
608}
609EXPORT_SYMBOL(ib_sa_unregister_client);
610
611/**
612 * ib_sa_cancel_query - try to cancel an SA query
613 * @id:ID of query to cancel
614 * @query:query pointer to cancel
615 *
616 * Try to cancel an SA query.  If the id and query don't match up or
617 * the query has already completed, nothing is done.  Otherwise the
618 * query is canceled and will complete with a status of -EINTR.
619 */
620void ib_sa_cancel_query(int id, struct ib_sa_query *query)
621{
622	unsigned long flags;
623	struct ib_mad_agent *agent;
624	struct ib_mad_send_buf *mad_buf;
625
626	spin_lock_irqsave(&idr_lock, flags);
627	if (idr_find(&query_idr, id) != query) {
628		spin_unlock_irqrestore(&idr_lock, flags);
629		return;
630	}
631	agent = query->port->agent;
632	mad_buf = query->mad_buf;
633	spin_unlock_irqrestore(&idr_lock, flags);
634
635	ib_cancel_mad(agent, mad_buf);
636}
637EXPORT_SYMBOL(ib_sa_cancel_query);
638
639static u8 get_src_path_mask(struct ib_device *device, u8 port_num)
640{
641	struct ib_sa_device *sa_dev;
642	struct ib_sa_port   *port;
643	unsigned long flags;
644	u8 src_path_mask;
645
646	sa_dev = ib_get_client_data(device, &sa_client);
647	if (!sa_dev)
648		return 0x7f;
649
650	port  = &sa_dev->port[port_num - sa_dev->start_port];
651	spin_lock_irqsave(&port->ah_lock, flags);
652	src_path_mask = port->sm_ah ? port->sm_ah->src_path_mask : 0x7f;
653	spin_unlock_irqrestore(&port->ah_lock, flags);
654
655	return src_path_mask;
656}
657
658int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
659			 struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr)
660{
661	int ret;
662	u16 gid_index;
663	int force_grh;
664
665	memset(ah_attr, 0, sizeof *ah_attr);
666	ah_attr->dlid = be16_to_cpu(rec->dlid);
667	ah_attr->sl = rec->sl;
668	ah_attr->src_path_bits = be16_to_cpu(rec->slid) &
669				 get_src_path_mask(device, port_num);
670	ah_attr->port_num = port_num;
671	ah_attr->static_rate = rec->rate;
672
673	force_grh = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_ETHERNET;
674
675	if (rec->hop_limit > 1 || force_grh) {
676		ah_attr->ah_flags = IB_AH_GRH;
677		ah_attr->grh.dgid = rec->dgid;
678
679		ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
680					 &gid_index);
681		if (ret)
682			return ret;
683
684		ah_attr->grh.sgid_index    = gid_index;
685		ah_attr->grh.flow_label    = be32_to_cpu(rec->flow_label);
686		ah_attr->grh.hop_limit     = rec->hop_limit;
687		ah_attr->grh.traffic_class = rec->traffic_class;
688	}
689	return 0;
690}
691EXPORT_SYMBOL(ib_init_ah_from_path);
692
693static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)
694{
695	unsigned long flags;
696
697	spin_lock_irqsave(&query->port->ah_lock, flags);
698	if (!query->port->sm_ah) {
699		spin_unlock_irqrestore(&query->port->ah_lock, flags);
700		return -EAGAIN;
701	}
702	kref_get(&query->port->sm_ah->ref);
703	query->sm_ah = query->port->sm_ah;
704	spin_unlock_irqrestore(&query->port->ah_lock, flags);
705
706	query->mad_buf = ib_create_send_mad(query->port->agent, 1,
707					    query->sm_ah->pkey_index,
708					    0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
709					    gfp_mask);
710	if (IS_ERR(query->mad_buf)) {
711		kref_put(&query->sm_ah->ref, free_sm_ah);
712		return -ENOMEM;
713	}
714
715	query->mad_buf->ah = query->sm_ah->ah;
716
717	return 0;
718}
719
720static void free_mad(struct ib_sa_query *query)
721{
722	ib_free_send_mad(query->mad_buf);
723	kref_put(&query->sm_ah->ref, free_sm_ah);
724}
725
726static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
727{
728	unsigned long flags;
729
730	memset(mad, 0, sizeof *mad);
731
732	mad->mad_hdr.base_version  = IB_MGMT_BASE_VERSION;
733	mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_SUBN_ADM;
734	mad->mad_hdr.class_version = IB_SA_CLASS_VERSION;
735
736	spin_lock_irqsave(&tid_lock, flags);
737	mad->mad_hdr.tid           =
738		cpu_to_be64(((u64) agent->hi_tid) << 32 | tid++);
739	spin_unlock_irqrestore(&tid_lock, flags);
740}
741
742static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
743{
744	unsigned long flags;
745	int ret, id;
746
747retry:
748	if (!idr_pre_get(&query_idr, gfp_mask))
749		return -ENOMEM;
750	spin_lock_irqsave(&idr_lock, flags);
751	ret = idr_get_new(&query_idr, query, &id);
752	spin_unlock_irqrestore(&idr_lock, flags);
753	if (ret == -EAGAIN)
754		goto retry;
755	if (ret)
756		return ret;
757
758	query->mad_buf->timeout_ms  = timeout_ms;
759	query->mad_buf->context[0] = query;
760	query->id = id;
761
762	ret = ib_post_send_mad(query->mad_buf, NULL);
763	if (ret) {
764		spin_lock_irqsave(&idr_lock, flags);
765		idr_remove(&query_idr, id);
766		spin_unlock_irqrestore(&idr_lock, flags);
767	}
768
769	/*
770	 * It's not safe to dereference query any more, because the
771	 * send may already have completed and freed the query in
772	 * another context.
773	 */
774	return ret ? ret : id;
775}
776
777void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec)
778{
779	ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), attribute, rec);
780}
781EXPORT_SYMBOL(ib_sa_unpack_path);
782
783static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
784				    int status,
785				    struct ib_sa_mad *mad)
786{
787	struct ib_sa_path_query *query =
788		container_of(sa_query, struct ib_sa_path_query, sa_query);
789
790	if (mad) {
791		struct ib_sa_path_rec rec;
792
793		ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
794			  mad->data, &rec);
795		query->callback(status, &rec, query->context);
796	} else
797		query->callback(status, NULL, query->context);
798}
799
800static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
801{
802	kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
803}
804
805int ib_sa_path_rec_query(struct ib_sa_client *client,
806			 struct ib_device *device, u8 port_num,
807			 struct ib_sa_path_rec *rec,
808			 ib_sa_comp_mask comp_mask,
809			 int timeout_ms, gfp_t gfp_mask,
810			 void (*callback)(int status,
811					  struct ib_sa_path_rec *resp,
812					  void *context),
813			 void *context,
814			 struct ib_sa_query **sa_query)
815{
816	struct ib_sa_path_query *query;
817	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
818	struct ib_sa_port   *port;
819	struct ib_mad_agent *agent;
820	struct ib_sa_mad *mad;
821	int ret;
822
823	if (!sa_dev)
824		return -ENODEV;
825
826	port  = &sa_dev->port[port_num - sa_dev->start_port];
827	agent = port->agent;
828
829	query = kmalloc(sizeof *query, gfp_mask);
830	if (!query)
831		return -ENOMEM;
832
833	query->sa_query.port     = port;
834	ret = alloc_mad(&query->sa_query, gfp_mask);
835	if (ret)
836		goto err1;
837
838	ib_sa_client_get(client);
839	query->sa_query.client = client;
840	query->callback        = callback;
841	query->context         = context;
842
843	mad = query->sa_query.mad_buf->mad;
844	init_mad(mad, agent);
845
846	query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
847	query->sa_query.release  = ib_sa_path_rec_release;
848	mad->mad_hdr.method	 = IB_MGMT_METHOD_GET;
849	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_PATH_REC);
850	mad->sa_hdr.comp_mask	 = comp_mask;
851
852	ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
853
854	*sa_query = &query->sa_query;
855
856	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
857	if (ret < 0)
858		goto err2;
859
860	return ret;
861
862err2:
863	*sa_query = NULL;
864	ib_sa_client_put(query->sa_query.client);
865	free_mad(&query->sa_query);
866
867err1:
868	kfree(query);
869	return ret;
870}
871
872static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
873				    int status,
874				    struct ib_sa_mad *mad)
875{
876	struct ib_sa_service_query *query =
877		container_of(sa_query, struct ib_sa_service_query, sa_query);
878
879	if (mad) {
880		struct ib_sa_service_rec rec;
881
882		ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),
883			  mad->data, &rec);
884		query->callback(status, &rec, query->context);
885	} else
886		query->callback(status, NULL, query->context);
887}
888
889static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
890{
891	kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
892}
893
894/**
895 * ib_sa_service_rec_query - Start Service Record operation
896 * @client:SA client
897 * @device:device to send request on
898 * @port_num: port number to send request on
899 * @method:SA method - should be get, set, or delete
900 * @rec:Service Record to send in request
901 * @comp_mask:component mask to send in request
902 * @timeout_ms:time to wait for response
903 * @gfp_mask:GFP mask to use for internal allocations
904 * @callback:function called when request completes, times out or is
905 * canceled
906 * @context:opaque user context passed to callback
907 * @sa_query:request context, used to cancel request
908 *
909 * Send a Service Record set/get/delete to the SA to register,
910 * unregister or query a service record.
911 * The callback function will be called when the request completes (or
912 * fails); status is 0 for a successful response, -EINTR if the query
913 * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
914 * occurred sending the query.  The resp parameter of the callback is
915 * only valid if status is 0.
916 *
917 * If the return value of ib_sa_service_rec_query() is negative, it is an
918 * error code.  Otherwise it is a request ID that can be used to cancel
919 * the query.
920 */
921int ib_sa_service_rec_query(struct ib_sa_client *client,
922			    struct ib_device *device, u8 port_num, u8 method,
923			    struct ib_sa_service_rec *rec,
924			    ib_sa_comp_mask comp_mask,
925			    int timeout_ms, gfp_t gfp_mask,
926			    void (*callback)(int status,
927					     struct ib_sa_service_rec *resp,
928					     void *context),
929			    void *context,
930			    struct ib_sa_query **sa_query)
931{
932	struct ib_sa_service_query *query;
933	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
934	struct ib_sa_port   *port;
935	struct ib_mad_agent *agent;
936	struct ib_sa_mad *mad;
937	int ret;
938
939	if (!sa_dev)
940		return -ENODEV;
941
942	port  = &sa_dev->port[port_num - sa_dev->start_port];
943	agent = port->agent;
944
945	if (method != IB_MGMT_METHOD_GET &&
946	    method != IB_MGMT_METHOD_SET &&
947	    method != IB_SA_METHOD_DELETE)
948		return -EINVAL;
949
950	query = kmalloc(sizeof *query, gfp_mask);
951	if (!query)
952		return -ENOMEM;
953
954	query->sa_query.port     = port;
955	ret = alloc_mad(&query->sa_query, gfp_mask);
956	if (ret)
957		goto err1;
958
959	ib_sa_client_get(client);
960	query->sa_query.client = client;
961	query->callback        = callback;
962	query->context         = context;
963
964	mad = query->sa_query.mad_buf->mad;
965	init_mad(mad, agent);
966
967	query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
968	query->sa_query.release  = ib_sa_service_rec_release;
969	mad->mad_hdr.method	 = method;
970	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
971	mad->sa_hdr.comp_mask	 = comp_mask;
972
973	ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
974		rec, mad->data);
975
976	*sa_query = &query->sa_query;
977
978	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
979	if (ret < 0)
980		goto err2;
981
982	return ret;
983
984err2:
985	*sa_query = NULL;
986	ib_sa_client_put(query->sa_query.client);
987	free_mad(&query->sa_query);
988
989err1:
990	kfree(query);
991	return ret;
992}
993EXPORT_SYMBOL(ib_sa_service_rec_query);
994
995static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
996					int status,
997					struct ib_sa_mad *mad)
998{
999	struct ib_sa_mcmember_query *query =
1000		container_of(sa_query, struct ib_sa_mcmember_query, sa_query);
1001
1002	if (mad) {
1003		struct ib_sa_mcmember_rec rec;
1004
1005		ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
1006			  mad->data, &rec);
1007		query->callback(status, &rec, query->context);
1008	} else
1009		query->callback(status, NULL, query->context);
1010}
1011
1012static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
1013{
1014	kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
1015}
1016
1017int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
1018			     struct ib_device *device, u8 port_num,
1019			     u8 method,
1020			     struct ib_sa_mcmember_rec *rec,
1021			     ib_sa_comp_mask comp_mask,
1022			     int timeout_ms, gfp_t gfp_mask,
1023			     void (*callback)(int status,
1024					      struct ib_sa_mcmember_rec *resp,
1025					      void *context),
1026			     void *context,
1027			     struct ib_sa_query **sa_query)
1028{
1029	struct ib_sa_mcmember_query *query;
1030	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
1031	struct ib_sa_port   *port;
1032	struct ib_mad_agent *agent;
1033	struct ib_sa_mad *mad;
1034	int ret;
1035
1036	if (!sa_dev)
1037		return -ENODEV;
1038
1039	port  = &sa_dev->port[port_num - sa_dev->start_port];
1040	agent = port->agent;
1041
1042	query = kmalloc(sizeof *query, gfp_mask);
1043	if (!query)
1044		return -ENOMEM;
1045
1046	query->sa_query.port     = port;
1047	ret = alloc_mad(&query->sa_query, gfp_mask);
1048	if (ret)
1049		goto err1;
1050
1051	ib_sa_client_get(client);
1052	query->sa_query.client = client;
1053	query->callback        = callback;
1054	query->context         = context;
1055
1056	mad = query->sa_query.mad_buf->mad;
1057	init_mad(mad, agent);
1058
1059	query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
1060	query->sa_query.release  = ib_sa_mcmember_rec_release;
1061	mad->mad_hdr.method	 = method;
1062	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
1063	mad->sa_hdr.comp_mask	 = comp_mask;
1064
1065	ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
1066		rec, mad->data);
1067
1068	*sa_query = &query->sa_query;
1069
1070	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
1071	if (ret < 0)
1072		goto err2;
1073
1074	return ret;
1075
1076err2:
1077	*sa_query = NULL;
1078	ib_sa_client_put(query->sa_query.client);
1079	free_mad(&query->sa_query);
1080
1081err1:
1082	kfree(query);
1083	return ret;
1084}
1085
1086static void ib_sa_inform_callback(struct ib_sa_query *sa_query,
1087				  int status,
1088				  struct ib_sa_mad *mad)
1089{
1090	struct ib_sa_inform_query *query =
1091		container_of(sa_query, struct ib_sa_inform_query, sa_query);
1092
1093	if (mad) {
1094		struct ib_sa_inform rec;
1095
1096		ib_unpack(inform_table, ARRAY_SIZE(inform_table),
1097			  mad->data, &rec);
1098		query->callback(status, &rec, query->context);
1099	} else
1100		query->callback(status, NULL, query->context);
1101}
1102
1103static void ib_sa_inform_release(struct ib_sa_query *sa_query)
1104{
1105	kfree(container_of(sa_query, struct ib_sa_inform_query, sa_query));
1106}
1107
1108int ib_sa_guid_info_rec_query(struct ib_sa_client *client,
1109			      struct ib_device *device, u8 port_num,
1110			      struct ib_sa_guidinfo_rec *rec,
1111			      ib_sa_comp_mask comp_mask, u8 method,
1112			      int timeout_ms, gfp_t gfp_mask,
1113			      void (*callback)(int status,
1114					       struct ib_sa_guidinfo_rec *resp,
1115					       void *context),
1116			      void *context,
1117			      struct ib_sa_query **sa_query)
1118{
1119	// stub function -
1120        // called originally from mad.c under mlx4_ib_init_sriov()
1121        // which calls mlx4_ib_init_alias_guid_service() in alias_GUID.c
1122        // which goes down to this function
1123
1124        printk("ERROR: function should be called only in SRIOV flow!!!");
1125
1126	return 0;
1127}
1128
1129/**
1130 * ib_sa_informinfo_query - Start an InformInfo registration.
1131 * @client:SA client
1132 * @device:device to send query on
1133 * @port_num: port number to send query on
1134 * @rec:Inform record to send in query
1135 * @timeout_ms:time to wait for response
1136 * @gfp_mask:GFP mask to use for internal allocations
1137 * @callback:function called when notice handler registration completes,
1138 * times out or is canceled
1139 * @context:opaque user context passed to callback
1140 * @sa_query:query context, used to cancel query
1141 *
1142 * This function sends inform info to register with SA to receive
1143 * in-service notice.
1144 * The callback function will be called when the query completes (or
1145 * fails); status is 0 for a successful response, -EINTR if the query
1146 * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
1147 * occurred sending the query.  The resp parameter of the callback is
1148 * only valid if status is 0.
1149 *
1150 * If the return value of ib_sa_inform_query() is negative, it is an
1151 * error code.  Otherwise it is a query ID that can be used to cancel
1152 * the query.
1153 */
1154int ib_sa_informinfo_query(struct ib_sa_client *client,
1155			   struct ib_device *device, u8 port_num,
1156			   struct ib_sa_inform *rec,
1157			   int timeout_ms, gfp_t gfp_mask,
1158			   void (*callback)(int status,
1159					   struct ib_sa_inform *resp,
1160					   void *context),
1161			   void *context,
1162			   struct ib_sa_query **sa_query)
1163{
1164	struct ib_sa_inform_query *query;
1165	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
1166	struct ib_sa_port   *port;
1167	struct ib_mad_agent *agent;
1168	struct ib_sa_mad *mad;
1169	int ret;
1170
1171	if (!sa_dev)
1172		return -ENODEV;
1173
1174	port  = &sa_dev->port[port_num - sa_dev->start_port];
1175	agent = port->agent;
1176
1177	query = kmalloc(sizeof *query, gfp_mask);
1178	if (!query)
1179		return -ENOMEM;
1180
1181	query->sa_query.port     = port;
1182	ret = alloc_mad(&query->sa_query, gfp_mask);
1183	if (ret)
1184		goto err1;
1185
1186	ib_sa_client_get(client);
1187	query->sa_query.client = client;
1188	query->callback = callback;
1189	query->context  = context;
1190
1191	mad = query->sa_query.mad_buf->mad;
1192	init_mad(mad, agent);
1193
1194	query->sa_query.callback = callback ? ib_sa_inform_callback : NULL;
1195	query->sa_query.release  = ib_sa_inform_release;
1196	query->sa_query.port     = port;
1197	mad->mad_hdr.method	 = IB_MGMT_METHOD_SET;
1198	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_INFORM_INFO);
1199
1200	ib_pack(inform_table, ARRAY_SIZE(inform_table), rec, mad->data);
1201
1202	*sa_query = &query->sa_query;
1203	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
1204	if (ret < 0)
1205		goto err2;
1206
1207	return ret;
1208
1209err2:
1210	*sa_query = NULL;
1211	ib_sa_client_put(query->sa_query.client);
1212	free_mad(&query->sa_query);
1213err1:
1214	kfree(query);
1215	return ret;
1216}
1217
1218static void ib_sa_notice_resp(struct ib_sa_port *port,
1219			      struct ib_mad_recv_wc *mad_recv_wc)
1220{
1221	struct ib_mad_send_buf *mad_buf;
1222	struct ib_sa_mad *mad;
1223	int ret;
1224	unsigned long flags;
1225
1226	mad_buf = ib_create_send_mad(port->notice_agent, 1, 0, 0,
1227				     IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
1228				     GFP_KERNEL);
1229	if (IS_ERR(mad_buf))
1230		return;
1231
1232	mad = mad_buf->mad;
1233	memcpy(mad, mad_recv_wc->recv_buf.mad, sizeof *mad);
1234	mad->mad_hdr.method = IB_MGMT_METHOD_REPORT_RESP;
1235
1236	spin_lock_irqsave(&port->ah_lock, flags);
1237	if (!port->sm_ah) {
1238		spin_unlock_irqrestore(&port->ah_lock, flags);
1239		ib_free_send_mad(mad_buf);
1240		return;
1241	}
1242	kref_get(&port->sm_ah->ref);
1243	mad_buf->context[0] = &port->sm_ah->ref;
1244	mad_buf->ah = port->sm_ah->ah;
1245	spin_unlock_irqrestore(&port->ah_lock, flags);
1246
1247	ret = ib_post_send_mad(mad_buf, NULL);
1248	if (ret)
1249		goto err;
1250
1251	return;
1252err:
1253	kref_put(mad_buf->context[0], free_sm_ah);
1254	ib_free_send_mad(mad_buf);
1255}
1256
1257static void send_handler(struct ib_mad_agent *agent,
1258			 struct ib_mad_send_wc *mad_send_wc)
1259{
1260	struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
1261	unsigned long flags;
1262
1263	if (query->callback)
1264		switch (mad_send_wc->status) {
1265		case IB_WC_SUCCESS:
1266			/* No callback -- already got recv */
1267			break;
1268		case IB_WC_RESP_TIMEOUT_ERR:
1269			query->callback(query, -ETIMEDOUT, NULL);
1270			break;
1271		case IB_WC_WR_FLUSH_ERR:
1272			query->callback(query, -EINTR, NULL);
1273			break;
1274		default:
1275			query->callback(query, -EIO, NULL);
1276			break;
1277		}
1278
1279	spin_lock_irqsave(&idr_lock, flags);
1280	idr_remove(&query_idr, query->id);
1281	spin_unlock_irqrestore(&idr_lock, flags);
1282
1283	free_mad(query);
1284	ib_sa_client_put(query->client);
1285	query->release(query);
1286}
1287
1288static void recv_handler(struct ib_mad_agent *mad_agent,
1289			 struct ib_mad_recv_wc *mad_recv_wc)
1290{
1291	struct ib_sa_query *query;
1292	struct ib_mad_send_buf *mad_buf;
1293
1294	mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
1295	query = mad_buf->context[0];
1296
1297	if (query->callback) {
1298		if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
1299			query->callback(query,
1300					mad_recv_wc->recv_buf.mad->mad_hdr.status ?
1301					-EINVAL : 0,
1302					(struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);
1303		else
1304			query->callback(query, -EIO, NULL);
1305	}
1306
1307	ib_free_recv_mad(mad_recv_wc);
1308}
1309
1310static void notice_resp_handler(struct ib_mad_agent *agent,
1311				struct ib_mad_send_wc *mad_send_wc)
1312{
1313	kref_put(mad_send_wc->send_buf->context[0], free_sm_ah);
1314	ib_free_send_mad(mad_send_wc->send_buf);
1315}
1316
1317static void notice_handler(struct ib_mad_agent *mad_agent,
1318			   struct ib_mad_recv_wc *mad_recv_wc)
1319{
1320	struct ib_sa_port *port;
1321	struct ib_sa_mad *mad;
1322	struct ib_sa_notice notice;
1323
1324	port = mad_agent->context;
1325	mad = (struct ib_sa_mad *) mad_recv_wc->recv_buf.mad;
1326	ib_unpack(notice_table, ARRAY_SIZE(notice_table), mad->data, &notice);
1327
1328	if (!notice_dispatch(port->device, port->port_num, &notice))
1329		ib_sa_notice_resp(port, mad_recv_wc);
1330	ib_free_recv_mad(mad_recv_wc);
1331}
1332
1333static void ib_sa_add_one(struct ib_device *device)
1334{
1335	struct ib_sa_device *sa_dev;
1336	struct ib_mad_reg_req reg_req = {
1337		.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
1338		.mgmt_class_version = 2
1339	};
1340	int s, e, i;
1341
1342	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
1343		return;
1344
1345	if (device->node_type == RDMA_NODE_IB_SWITCH)
1346		s = e = 0;
1347	else {
1348		s = 1;
1349		e = device->phys_port_cnt;
1350	}
1351
1352	sa_dev = kzalloc(sizeof *sa_dev +
1353			 (e - s + 1) * sizeof (struct ib_sa_port),
1354			 GFP_KERNEL);
1355	if (!sa_dev)
1356		return;
1357
1358	sa_dev->start_port = s;
1359	sa_dev->end_port   = e;
1360
1361	for (i = 0; i <= e - s; ++i) {
1362		spin_lock_init(&sa_dev->port[i].ah_lock);
1363		if (rdma_port_get_link_layer(device, i + 1) != IB_LINK_LAYER_INFINIBAND)
1364			continue;
1365
1366		sa_dev->port[i].sm_ah    = NULL;
1367		sa_dev->port[i].port_num = i + s;
1368
1369		sa_dev->port[i].agent =
1370			ib_register_mad_agent(device, i + s, IB_QPT_GSI,
1371					      NULL, 0, send_handler,
1372					      recv_handler, sa_dev);
1373		if (IS_ERR(sa_dev->port[i].agent))
1374			goto err;
1375
1376		sa_dev->port[i].device = device;
1377		set_bit(IB_MGMT_METHOD_REPORT, reg_req.method_mask);
1378		sa_dev->port[i].notice_agent =
1379			ib_register_mad_agent(device, i + s, IB_QPT_GSI,
1380					      &reg_req, 0, notice_resp_handler,
1381					      notice_handler, &sa_dev->port[i]);
1382
1383		if (IS_ERR(sa_dev->port[i].notice_agent))
1384			goto err;
1385
1386		INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);
1387	}
1388
1389	ib_set_client_data(device, &sa_client, sa_dev);
1390
1391	/*
1392	 * We register our event handler after everything is set up,
1393	 * and then update our cached info after the event handler is
1394	 * registered to avoid any problems if a port changes state
1395	 * during our initialization.
1396	 */
1397
1398	INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);
1399	if (ib_register_event_handler(&sa_dev->event_handler))
1400		goto err;
1401
1402	for (i = 0; i <= e - s; ++i)
1403		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND)
1404			update_sm_ah(&sa_dev->port[i].update_task);
1405
1406	return;
1407
1408err:
1409	while (--i >= 0)
1410		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) {
1411			if (!IS_ERR(sa_dev->port[i].notice_agent))
1412				ib_unregister_mad_agent(sa_dev->port[i].notice_agent);
1413			if (!IS_ERR(sa_dev->port[i].agent))
1414				ib_unregister_mad_agent(sa_dev->port[i].agent);
1415		}
1416
1417	kfree(sa_dev);
1418
1419	return;
1420}
1421
1422static void ib_sa_remove_one(struct ib_device *device)
1423{
1424	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
1425	int i;
1426
1427	if (!sa_dev)
1428		return;
1429
1430	ib_unregister_event_handler(&sa_dev->event_handler);
1431
1432	flush_scheduled_work();
1433
1434	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
1435		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) {
1436			ib_unregister_mad_agent(sa_dev->port[i].notice_agent);
1437			ib_unregister_mad_agent(sa_dev->port[i].agent);
1438			if (sa_dev->port[i].sm_ah)
1439				kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
1440		}
1441
1442	}
1443
1444	kfree(sa_dev);
1445}
1446
1447static int __init ib_sa_init(void)
1448{
1449	int ret;
1450
1451	spin_lock_init(&idr_lock);
1452	spin_lock_init(&tid_lock);
1453
1454	get_random_bytes(&tid, sizeof tid);
1455
1456	ret = ib_register_client(&sa_client);
1457	if (ret) {
1458		printk(KERN_ERR "Couldn't register ib_sa client\n");
1459		goto err1;
1460	}
1461
1462	ret = mcast_init();
1463	if (ret) {
1464		printk(KERN_ERR "Couldn't initialize multicast handling\n");
1465		goto err2;
1466	}
1467
1468	ret = notice_init();
1469	if (ret) {
1470		printk(KERN_ERR "Couldn't initialize notice handling\n");
1471		goto err3;
1472	}
1473
1474	ret = sa_db_init();
1475	if (ret) {
1476		printk(KERN_ERR "Couldn't initialize local SA\n");
1477		goto err4;
1478	}
1479
1480	return 0;
1481err4:
1482	notice_cleanup();
1483err3:
1484	mcast_cleanup();
1485err2:
1486	ib_unregister_client(&sa_client);
1487err1:
1488	return ret;
1489}
1490
1491static void __exit ib_sa_cleanup(void)
1492{
1493	sa_db_cleanup();
1494	mcast_cleanup();
1495	notice_cleanup();
1496	ib_unregister_client(&sa_client);
1497	idr_destroy(&query_idr);
1498}
1499
1500module_init_order(ib_sa_init, SI_ORDER_SECOND);
1501module_exit(ib_sa_cleanup);
1502