1 /*
2  * Copyright (c) 2012 Mellanox Technologies. 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  /***********************************************************/
33 /*This file support the handling of the Alias GUID feature. */
34 /***********************************************************/
35 #include <rdma/ib_mad.h>
36 #include <rdma/ib_smi.h>
37 #include <rdma/ib_cache.h>
38 #include <rdma/ib_sa.h>
39 #include <rdma/ib_pack.h>
40 #include <linux/mlx4/cmd.h>
41 #include <linux/module.h>
42 #include <linux/errno.h>
43 #include <rdma/ib_user_verbs.h>
44 #include <linux/delay.h>
45 #include "mlx4_ib.h"
46 
47 /*
48 The driver keeps the current state of all guids, as they are in the HW.
49 Whenever we receive an smp mad GUIDInfo record, the data will be cached.
50 */
51 
52 struct mlx4_alias_guid_work_context {
53 	u8 port;
54 	struct mlx4_ib_dev     *dev ;
55 	struct ib_sa_query     *sa_query;
56 	struct completion	done;
57 	int			query_id;
58 	struct list_head	list;
59 	int			block_num;
60 };
61 
62 struct mlx4_next_alias_guid_work {
63 	u8 port;
64 	u8 block_num;
65 	struct mlx4_sriov_alias_guid_info_rec_det rec_det;
66 };
67 
68 
mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev * dev,int block_num,u8 port_num,u8 * p_data)69 void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
70 					 u8 port_num, u8 *p_data)
71 {
72 	int i;
73 	u64 guid_indexes;
74 	int slave_id;
75 	int port_index = port_num - 1;
76 
77 	if (!mlx4_is_master(dev->dev))
78 		return;
79 
80 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
81 				   ports_guid[port_num - 1].
82 				   all_rec_per_port[block_num].guid_indexes);
83 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, (long long)guid_indexes);
84 
85 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
86 		/* The location of the specific index starts from bit number 4
87 		 * until bit num 11 */
88 		if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
89 			slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
90 			if (slave_id >= dev->dev->num_slaves) {
91 				pr_debug("The last slave: %d\n", slave_id);
92 				return;
93 			}
94 
95 			/* cache the guid: */
96 			memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
97 			       &p_data[i * GUID_REC_SIZE],
98 			       GUID_REC_SIZE);
99 		} else
100 			pr_debug("Guid number: %d in block: %d"
101 				 " was not updated\n", i, block_num);
102 	}
103 }
104 
get_cached_alias_guid(struct mlx4_ib_dev * dev,int port,int index)105 static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
106 {
107 	if (index >= NUM_ALIAS_GUID_PER_PORT) {
108 		pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
109 		return (__force __be64) -1;
110 	}
111 	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
112 }
113 
114 
mlx4_ib_get_aguid_comp_mask_from_ix(int index)115 ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
116 {
117 	return IB_SA_COMP_MASK(4 + index);
118 }
119 
120 /*
121  * Whenever new GUID is set/unset (guid table change) create event and
122  * notify the relevant slave (master also should be notified).
123  * If the GUID value is not as we have in the cache the slave will not be
124  * updated; in this case it waits for the smp_snoop or the port management
125  * event to call the function and to update the slave.
126  * block_number - the index of the block (16 blocks available)
127  * port_number - 1 or 2
128  */
mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev * dev,int block_num,u8 port_num,u8 * p_data)129 void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
130 					  int block_num, u8 port_num,
131 					  u8 *p_data)
132 {
133 	int i;
134 	u64 guid_indexes;
135 	int slave_id;
136 	enum slave_port_state new_state;
137 	enum slave_port_state prev_state;
138 	__be64 tmp_cur_ag, form_cache_ag;
139 	enum slave_port_gen_event gen_event;
140 
141 	if (!mlx4_is_master(dev->dev))
142 		return;
143 
144 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
145 				   ports_guid[port_num - 1].
146 				   all_rec_per_port[block_num].guid_indexes);
147 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, (long long)guid_indexes);
148 
149 	/*calculate the slaves and notify them*/
150 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
151 		/* the location of the specific index runs from bits 4..11 */
152 		if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
153 			continue;
154 
155 		slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
156 		if (slave_id >= dev->dev->num_slaves)
157 			return;
158 		tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
159 		form_cache_ag = get_cached_alias_guid(dev, port_num,
160 					(NUM_ALIAS_GUID_IN_REC * block_num) + i);
161 		/*
162 		 * Check if guid is not the same as in the cache,
163 		 * If it is different, wait for the snoop_smp or the port mgmt
164 		 * change event to update the slave on its port state change
165 		 */
166 		if (tmp_cur_ag != form_cache_ag)
167 			continue;
168 		mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
169 
170 		/*2 cases: Valid GUID, and Invalid Guid*/
171 
172 		if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
173 			prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
174 			new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
175 								  MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
176 								  &gen_event);
177 			pr_debug("slave: %d, port: %d prev_port_state: %d,"
178 				 " new_port_state: %d, gen_event: %d\n",
179 				 slave_id, port_num, prev_state, new_state, gen_event);
180 			if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
181 				pr_debug("sending PORT_UP event to slave: %d, port: %d\n",
182 					 slave_id, port_num);
183 				mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
184 							       port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
185 			}
186 		} else { /* request to invalidate GUID */
187 			set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
188 						      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
189 						      &gen_event);
190 			pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
191 				 slave_id, port_num);
192 			mlx4_gen_port_state_change_eqe(dev->dev, slave_id, port_num,
193 						       MLX4_PORT_CHANGE_SUBTYPE_DOWN);
194 		}
195 	}
196 }
197 
aliasguid_query_handler(int status,struct ib_sa_guidinfo_rec * guid_rec,void * context)198 static void aliasguid_query_handler(int status,
199 				    struct ib_sa_guidinfo_rec *guid_rec,
200 				    void *context)
201 {
202 	struct mlx4_ib_dev *dev;
203 	struct mlx4_alias_guid_work_context *cb_ctx = context;
204 	u8 port_index ;
205 	int i;
206 	struct mlx4_sriov_alias_guid_info_rec_det *rec;
207 	unsigned long flags, flags1;
208 
209 	if (!context)
210 		return;
211 
212 	dev = cb_ctx->dev;
213 	port_index = cb_ctx->port - 1;
214 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
215 		all_rec_per_port[cb_ctx->block_num];
216 
217 	if (status) {
218 		rec->status = MLX4_GUID_INFO_STATUS_IDLE;
219 		pr_debug("(port: %d) failed: status = %d\n",
220 			 cb_ctx->port, status);
221 		goto out;
222 	}
223 
224 	if (guid_rec->block_num != cb_ctx->block_num) {
225 		pr_err("block num mismatch: %d != %d\n",
226 		       cb_ctx->block_num, guid_rec->block_num);
227 		goto out;
228 	}
229 
230 	pr_debug("lid/port: %d/%d, block_num: %d\n",
231 		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
232 		 guid_rec->block_num);
233 
234 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
235 		all_rec_per_port[guid_rec->block_num];
236 
237 	rec->status = MLX4_GUID_INFO_STATUS_SET;
238 	rec->method = MLX4_GUID_INFO_RECORD_SET;
239 
240 	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
241 		__be64 tmp_cur_ag;
242 		tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
243 		/* check if the SM didn't assign one of the records.
244 		 * if it didn't, if it was not sysadmin request:
245 		 * ask the SM to give a new GUID, (instead of the driver request).
246 		 */
247 		if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
248 			mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
249 				     "block_num: %d was declined by SM, "
250 				     "ownership by %d (0 = driver, 1=sysAdmin,"
251 				     " 2=None)\n", __func__, i,
252 				     guid_rec->block_num, rec->ownership);
253 			if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
254 				/* if it is driver assign, asks for new GUID from SM*/
255 				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
256 					MLX4_NOT_SET_GUID;
257 
258 				/* Mark the record as not assigned, and let it
259 				 * be sent again in the next work sched.*/
260 				rec->status = MLX4_GUID_INFO_STATUS_IDLE;
261 				rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
262 			}
263 		} else {
264 		       /* properly assigned record. */
265 		       /* We save the GUID we just got from the SM in the
266 			* admin_guid in order to be persistent, and in the
267 			* request from the sm the process will ask for the same GUID */
268 			if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
269 			    tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
270 				/* the sysadmin assignment failed.*/
271 				mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
272 					     " admin guid after SysAdmin "
273 					     "configuration. "
274 					     "Record num %d in block_num:%d "
275 					     "was declined by SM, "
276 					     "new val(0x%llx) was kept\n",
277 					      __func__, i,
278 					     guid_rec->block_num,
279 					     (long long)be64_to_cpu(*(__be64 *) &
280 							 rec->all_recs[i * GUID_REC_SIZE]));
281 			} else {
282 				memcpy(&rec->all_recs[i * GUID_REC_SIZE],
283 				       &guid_rec->guid_info_list[i * GUID_REC_SIZE],
284 				       GUID_REC_SIZE);
285 			}
286 		}
287 	}
288 	/*
289 	The func is call here to close the cases when the
290 	sm doesn't send smp, so in the sa response the driver
291 	notifies the slave.
292 	*/
293 	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
294 					     cb_ctx->port,
295 					     guid_rec->guid_info_list);
296 out:
297 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
298 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
299 	if (!dev->sriov.is_going_down)
300 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
301 				   &dev->sriov.alias_guid.ports_guid[port_index].
302 				   alias_guid_work, 0);
303 	if (cb_ctx->sa_query) {
304 		list_del(&cb_ctx->list);
305 		kfree(cb_ctx);
306 	} else
307 		complete(&cb_ctx->done);
308 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
309 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
310 }
311 
invalidate_guid_record(struct mlx4_ib_dev * dev,u8 port,int index)312 static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
313 {
314 	int i;
315 	u64 cur_admin_val;
316 	ib_sa_comp_mask comp_mask = 0;
317 
318 	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
319 		= MLX4_GUID_INFO_STATUS_IDLE;
320 	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method
321 		= MLX4_GUID_INFO_RECORD_SET;
322 
323 	/* calculate the comp_mask for that record.*/
324 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
325 		cur_admin_val =
326 			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
327 			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
328 		/*
329 		check the admin value: if it's for delete (~00LL) or
330 		it is the first guid of the first record (hw guid) or
331 		the records is not in ownership of the sysadmin and the sm doesn't
332 		need to assign GUIDs, then don't put it up for assignment.
333 		*/
334 		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
335 		    (!index && !i) ||
336 		    MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
337 		    ports_guid[port - 1].all_rec_per_port[index].ownership)
338 			continue;
339 		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
340 	}
341 	dev->sriov.alias_guid.ports_guid[port - 1].
342 		all_rec_per_port[index].guid_indexes = comp_mask;
343 }
344 
set_guid_rec(struct ib_device * ibdev,u8 port,int index,struct mlx4_sriov_alias_guid_info_rec_det * rec_det)345 static int set_guid_rec(struct ib_device *ibdev,
346 			u8 port, int index,
347 			struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
348 {
349 	int err;
350 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
351 	struct ib_sa_guidinfo_rec guid_info_rec;
352 	ib_sa_comp_mask comp_mask;
353 	struct ib_port_attr attr;
354 	struct mlx4_alias_guid_work_context *callback_context;
355 	unsigned long resched_delay, flags, flags1;
356 	struct list_head *head =
357 		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
358 
359 	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
360 	if (err) {
361 		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
362 			 err, port);
363 		return err;
364 	}
365 	/*check the port was configured by the sm, otherwise no need to send */
366 	if (attr.state != IB_PORT_ACTIVE) {
367 		pr_debug("port %d not active...rescheduling\n", port);
368 		resched_delay = 5 * HZ;
369 		err = -EAGAIN;
370 		goto new_schedule;
371 	}
372 
373 	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
374 	if (!callback_context) {
375 		err = -ENOMEM;
376 		resched_delay = HZ * 5;
377 		goto new_schedule;
378 	}
379 	callback_context->port = port;
380 	callback_context->dev = dev;
381 	callback_context->block_num = index;
382 
383 	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
384 
385 	guid_info_rec.lid = cpu_to_be16(attr.lid);
386 	guid_info_rec.block_num = index;
387 
388 	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
389 	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
390 	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
391 		rec_det->guid_indexes;
392 
393 	init_completion(&callback_context->done);
394 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
395 	list_add_tail(&callback_context->list, head);
396 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
397 
398 	callback_context->query_id =
399 		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
400 					  ibdev, port, &guid_info_rec,
401 					  comp_mask, rec_det->method, 1000,
402 					  GFP_KERNEL, aliasguid_query_handler,
403 					  callback_context,
404 					  &callback_context->sa_query);
405 	if (callback_context->query_id < 0) {
406 		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
407 			 "%d. will reschedule to the next 1 sec.\n",
408 			 callback_context->query_id);
409 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
410 		list_del(&callback_context->list);
411 		kfree(callback_context);
412 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
413 		resched_delay = 1 * HZ;
414 		err = -EAGAIN;
415 		goto new_schedule;
416 	}
417 	err = 0;
418 	goto out;
419 
420 new_schedule:
421 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
422 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
423 	invalidate_guid_record(dev, port, index);
424 	if (!dev->sriov.is_going_down) {
425 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
426 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
427 				   resched_delay);
428 	}
429 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
430 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
431 
432 out:
433 	return err;
434 }
435 
mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev * dev,int port)436 void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
437 {
438 	int i;
439 	unsigned long flags, flags1;
440 
441 	pr_debug("port %d\n", port);
442 
443 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
444 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
445 	for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
446 		invalidate_guid_record(dev, port, i);
447 
448 	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
449 		/*
450 		make sure no work waits in the queue, if the work is already
451 		queued(not on the timer) the cancel will fail. That is not a problem
452 		because we just want the work started.
453 		*/
454 		cancel_delayed_work(&dev->sriov.alias_guid.
455 				      ports_guid[port - 1].alias_guid_work);
456 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
457 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
458 				   0);
459 	}
460 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
461 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
462 }
463 
464 /* The function returns the next record that was
465  * not configured (or failed to be configured) */
get_next_record_to_update(struct mlx4_ib_dev * dev,u8 port,struct mlx4_next_alias_guid_work * rec)466 static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
467 				     struct mlx4_next_alias_guid_work *rec)
468 {
469 	int j;
470 	unsigned long flags;
471 
472 	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
473 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
474 		if (dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status ==
475 		    MLX4_GUID_INFO_STATUS_IDLE) {
476 			memcpy(&rec->rec_det,
477 			       &dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j],
478 			       sizeof (struct mlx4_sriov_alias_guid_info_rec_det));
479 			rec->port = port;
480 			rec->block_num = j;
481 			dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status =
482 				MLX4_GUID_INFO_STATUS_PENDING;
483 			spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
484 			return 0;
485 		}
486 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
487 	}
488 	return -ENOENT;
489 }
490 
set_administratively_guid_record(struct mlx4_ib_dev * dev,int port,int rec_index,struct mlx4_sriov_alias_guid_info_rec_det * rec_det)491 static void set_administratively_guid_record(struct mlx4_ib_dev *dev, int port,
492 					     int rec_index,
493 					     struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
494 {
495 	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].guid_indexes =
496 		rec_det->guid_indexes;
497 	memcpy(dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].all_recs,
498 	       rec_det->all_recs, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
499 	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].status =
500 		rec_det->status;
501 }
502 
set_all_slaves_guids(struct mlx4_ib_dev * dev,int port)503 static void set_all_slaves_guids(struct mlx4_ib_dev *dev, int port)
504 {
505 	int j;
506 	struct mlx4_sriov_alias_guid_info_rec_det rec_det ;
507 
508 	for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT ; j++) {
509 		memset(rec_det.all_recs, 0, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
510 		rec_det.guid_indexes = (!j ? 0 : IB_SA_GUIDINFO_REC_GID0) |
511 			IB_SA_GUIDINFO_REC_GID1 | IB_SA_GUIDINFO_REC_GID2 |
512 			IB_SA_GUIDINFO_REC_GID3 | IB_SA_GUIDINFO_REC_GID4 |
513 			IB_SA_GUIDINFO_REC_GID5 | IB_SA_GUIDINFO_REC_GID6 |
514 			IB_SA_GUIDINFO_REC_GID7;
515 		rec_det.status = MLX4_GUID_INFO_STATUS_IDLE;
516 		set_administratively_guid_record(dev, port, j, &rec_det);
517 	}
518 }
519 
alias_guid_work(struct work_struct * work)520 static void alias_guid_work(struct work_struct *work)
521 {
522 	struct delayed_work *delay = to_delayed_work(work);
523 	int ret = 0;
524 	struct mlx4_next_alias_guid_work *rec;
525 	struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
526 		container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
527 			     alias_guid_work);
528 	struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
529 	struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
530 						struct mlx4_ib_sriov,
531 						alias_guid);
532 	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
533 
534 	rec = kzalloc(sizeof *rec, GFP_KERNEL);
535 	if (!rec) {
536 		pr_err("alias_guid_work: No Memory\n");
537 		return;
538 	}
539 
540 	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
541 	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
542 	if (ret) {
543 		pr_debug("No more records to update.\n");
544 		goto out;
545 	}
546 
547 	set_guid_rec(&dev->ib_dev, rec->port + 1, rec->block_num,
548 		     &rec->rec_det);
549 
550 out:
551 	kfree(rec);
552 }
553 
554 
mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev * dev,int port)555 void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
556 {
557 	unsigned long flags, flags1;
558 
559 	if (!mlx4_is_master(dev->dev))
560 		return;
561 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
562 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
563 	if (!dev->sriov.is_going_down) {
564 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
565 			   &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
566 	}
567 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
568 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
569 }
570 
mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev * dev)571 void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
572 {
573 	int i;
574 	struct mlx4_ib_sriov *sriov = &dev->sriov;
575 	struct mlx4_alias_guid_work_context *cb_ctx;
576 	struct mlx4_sriov_alias_guid_port_rec_det *det;
577 	struct ib_sa_query *sa_query;
578 	unsigned long flags;
579 
580 	for (i = 0 ; i < dev->num_ports; i++) {
581 		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
582 		det = &sriov->alias_guid.ports_guid[i];
583 		spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
584 		while (!list_empty(&det->cb_list)) {
585 			cb_ctx = list_entry(det->cb_list.next,
586 					    struct mlx4_alias_guid_work_context,
587 					    list);
588 			sa_query = cb_ctx->sa_query;
589 			cb_ctx->sa_query = NULL;
590 			list_del(&cb_ctx->list);
591 			spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
592 			ib_sa_cancel_query(cb_ctx->query_id, sa_query);
593 			wait_for_completion(&cb_ctx->done);
594 			kfree(cb_ctx);
595 			spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
596 		}
597 		spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
598 	}
599 	for (i = 0 ; i < dev->num_ports; i++) {
600 		flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
601 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
602 	}
603 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
604 	kfree(dev->sriov.alias_guid.sa_client);
605 }
606 
mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev * dev)607 int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
608 {
609 	char alias_wq_name[15];
610 	int ret = 0;
611 	int i, j, k;
612 	union ib_gid gid;
613 
614 	if (!mlx4_is_master(dev->dev))
615 		return 0;
616 	dev->sriov.alias_guid.sa_client =
617 		kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
618 	if (!dev->sriov.alias_guid.sa_client)
619 		return -ENOMEM;
620 
621 	ib_sa_register_client(dev->sriov.alias_guid.sa_client);
622 
623 	spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
624 
625 	for (i = 1; i <= dev->num_ports; ++i) {
626 		if (dev->ib_dev.query_gid(&dev->ib_dev , i, 0, &gid)) {
627 			ret = -EFAULT;
628 			goto err_unregister;
629 		}
630 	}
631 
632 	for (i = 0 ; i < dev->num_ports; i++) {
633 		memset(&dev->sriov.alias_guid.ports_guid[i], 0,
634 		       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
635 		/*Check if the SM doesn't need to assign the GUIDs*/
636 		for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
637 			if (mlx4_ib_sm_guid_assign) {
638 				dev->sriov.alias_guid.ports_guid[i].
639 					all_rec_per_port[j].
640 					ownership = MLX4_GUID_DRIVER_ASSIGN;
641 				continue;
642 			}
643 			dev->sriov.alias_guid.ports_guid[i].all_rec_per_port[j].
644 					ownership = MLX4_GUID_NONE_ASSIGN;
645 			/*mark each val as it was deleted,
646 			  till the sysAdmin will give it valid val*/
647 			for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
648 				*(__be64 *)&dev->sriov.alias_guid.ports_guid[i].
649 					all_rec_per_port[j].all_recs[GUID_REC_SIZE * k] =
650 						cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
651 			}
652 		}
653 		INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
654 		/*prepare the records, set them to be allocated by sm*/
655 		for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
656 			invalidate_guid_record(dev, i + 1, j);
657 
658 		dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
659 		dev->sriov.alias_guid.ports_guid[i].port  = i;
660 		if (mlx4_ib_sm_guid_assign)
661 			set_all_slaves_guids(dev, i);
662 
663 		snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
664 		dev->sriov.alias_guid.ports_guid[i].wq =
665 			create_singlethread_workqueue(alias_wq_name);
666 		if (!dev->sriov.alias_guid.ports_guid[i].wq) {
667 			ret = -ENOMEM;
668 			goto err_thread;
669 		}
670 		INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
671 			  alias_guid_work);
672 	}
673 	return 0;
674 
675 err_thread:
676 	for (--i; i >= 0; i--) {
677 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
678 		dev->sriov.alias_guid.ports_guid[i].wq = NULL;
679 	}
680 
681 err_unregister:
682 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
683 	kfree(dev->sriov.alias_guid.sa_client);
684 	dev->sriov.alias_guid.sa_client = NULL;
685 	pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
686 	return ret;
687 }
688