xref: /freebsd/sys/dev/mlx4/mlx4_ib/mlx4_ib_alias_GUID.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
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 <dev/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 <linux/math64.h>
46 #include <linux/ktime.h>
47 #include "mlx4_ib.h"
48 
49 /*
50 The driver keeps the current state of all guids, as they are in the HW.
51 Whenever we receive an smp mad GUIDInfo record, the data will be cached.
52 */
53 
54 struct mlx4_alias_guid_work_context {
55 	u8 port;
56 	struct mlx4_ib_dev     *dev ;
57 	struct ib_sa_query     *sa_query;
58 	struct completion	done;
59 	int			query_id;
60 	struct list_head	list;
61 	int			block_num;
62 	ib_sa_comp_mask		guid_indexes;
63 	u8			method;
64 };
65 
66 struct mlx4_next_alias_guid_work {
67 	u8 port;
68 	u8 block_num;
69 	u8 method;
70 	struct mlx4_sriov_alias_guid_info_rec_det rec_det;
71 };
72 
73 static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
74 				     int *resched_delay_sec);
75 
mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev * dev,int block_num,u8 port_num,u8 * p_data)76 void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
77 					 u8 port_num, u8 *p_data)
78 {
79 	int i;
80 	u64 guid_indexes;
81 	int slave_id;
82 	int port_index = port_num - 1;
83 
84 	if (!mlx4_is_master(dev->dev))
85 		return;
86 
87 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
88 				   ports_guid[port_num - 1].
89 				   all_rec_per_port[block_num].guid_indexes);
90 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num,
91 	    (unsigned long long)guid_indexes);
92 
93 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
94 		/* The location of the specific index starts from bit number 4
95 		 * until bit num 11 */
96 		if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
97 			slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
98 			if (slave_id >= dev->dev->num_slaves) {
99 				pr_debug("The last slave: %d\n", slave_id);
100 				return;
101 			}
102 
103 			/* cache the guid: */
104 			memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
105 			       &p_data[i * GUID_REC_SIZE],
106 			       GUID_REC_SIZE);
107 		} else
108 			pr_debug("Guid number: %d in block: %d"
109 				 " was not updated\n", i, block_num);
110 	}
111 }
112 
get_cached_alias_guid(struct mlx4_ib_dev * dev,int port,int index)113 static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
114 {
115 	if (index >= NUM_ALIAS_GUID_PER_PORT) {
116 		pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
117 		return (__force __be64) -1;
118 	}
119 	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
120 }
121 
122 
mlx4_ib_get_aguid_comp_mask_from_ix(int index)123 ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
124 {
125 	return IB_SA_COMP_MASK(4 + index);
126 }
127 
mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev * dev,int slave,int port,int slave_init)128 void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
129 				    int port,  int slave_init)
130 {
131 	__be64 curr_guid, required_guid;
132 	int record_num = slave / 8;
133 	int index = slave % 8;
134 	int port_index = port - 1;
135 	unsigned long flags;
136 	int do_work = 0;
137 
138 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
139 	if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
140 	    GUID_STATE_NEED_PORT_INIT)
141 		goto unlock;
142 	if (!slave_init) {
143 		curr_guid = *(__be64 *)&dev->sriov.
144 			alias_guid.ports_guid[port_index].
145 			all_rec_per_port[record_num].
146 			all_recs[GUID_REC_SIZE * index];
147 		if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
148 		    !curr_guid)
149 			goto unlock;
150 		required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
151 	} else {
152 		required_guid = mlx4_get_admin_guid(dev->dev, slave, port);
153 		if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
154 			goto unlock;
155 	}
156 	*(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
157 		all_rec_per_port[record_num].
158 		all_recs[GUID_REC_SIZE * index] = required_guid;
159 	dev->sriov.alias_guid.ports_guid[port_index].
160 		all_rec_per_port[record_num].guid_indexes
161 		|= mlx4_ib_get_aguid_comp_mask_from_ix(index);
162 	dev->sriov.alias_guid.ports_guid[port_index].
163 		all_rec_per_port[record_num].status
164 		= MLX4_GUID_INFO_STATUS_IDLE;
165 	/* set to run immediately */
166 	dev->sriov.alias_guid.ports_guid[port_index].
167 		all_rec_per_port[record_num].time_to_run = 0;
168 	dev->sriov.alias_guid.ports_guid[port_index].
169 		all_rec_per_port[record_num].
170 		guids_retry_schedule[index] = 0;
171 	do_work = 1;
172 unlock:
173 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
174 
175 	if (do_work)
176 		mlx4_ib_init_alias_guid_work(dev, port_index);
177 }
178 
179 /*
180  * Whenever new GUID is set/unset (guid table change) create event and
181  * notify the relevant slave (master also should be notified).
182  * If the GUID value is not as we have in the cache the slave will not be
183  * updated; in this case it waits for the smp_snoop or the port management
184  * event to call the function and to update the slave.
185  * block_number - the index of the block (16 blocks available)
186  * port_number - 1 or 2
187  */
mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev * dev,int block_num,u8 port_num,u8 * p_data)188 void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
189 					  int block_num, u8 port_num,
190 					  u8 *p_data)
191 {
192 	int i;
193 	u64 guid_indexes;
194 	int slave_id, slave_port;
195 	enum slave_port_state new_state;
196 	enum slave_port_state prev_state;
197 	__be64 tmp_cur_ag, form_cache_ag;
198 	enum slave_port_gen_event gen_event;
199 	struct mlx4_sriov_alias_guid_info_rec_det *rec;
200 	unsigned long flags;
201 	__be64 required_value;
202 
203 	if (!mlx4_is_master(dev->dev))
204 		return;
205 
206 	rec = &dev->sriov.alias_guid.ports_guid[port_num - 1].
207 			all_rec_per_port[block_num];
208 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
209 				   ports_guid[port_num - 1].
210 				   all_rec_per_port[block_num].guid_indexes);
211 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num,
212 	    (unsigned long long)guid_indexes);
213 
214 	/*calculate the slaves and notify them*/
215 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
216 		/* the location of the specific index runs from bits 4..11 */
217 		if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
218 			continue;
219 
220 		slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
221 		if (slave_id >= dev->dev->persist->num_vfs + 1)
222 			return;
223 
224 		slave_port = mlx4_phys_to_slave_port(dev->dev, slave_id, port_num);
225 		if (slave_port < 0) /* this port isn't available for the VF */
226 			continue;
227 
228 		tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
229 		form_cache_ag = get_cached_alias_guid(dev, port_num,
230 					(NUM_ALIAS_GUID_IN_REC * block_num) + i);
231 		/*
232 		 * Check if guid is not the same as in the cache,
233 		 * If it is different, wait for the snoop_smp or the port mgmt
234 		 * change event to update the slave on its port state change
235 		 */
236 		if (tmp_cur_ag != form_cache_ag)
237 			continue;
238 
239 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
240 		required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
241 
242 		if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
243 			required_value = 0;
244 
245 		if (tmp_cur_ag == required_value) {
246 			rec->guid_indexes = rec->guid_indexes &
247 			       ~mlx4_ib_get_aguid_comp_mask_from_ix(i);
248 		} else {
249 			/* may notify port down if value is 0 */
250 			if (tmp_cur_ag != MLX4_NOT_SET_GUID) {
251 				spin_unlock_irqrestore(&dev->sriov.
252 					alias_guid.ag_work_lock, flags);
253 				continue;
254 			}
255 		}
256 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock,
257 				       flags);
258 		mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
259 		/*2 cases: Valid GUID, and Invalid Guid*/
260 
261 		if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
262 			prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
263 			new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
264 								  MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
265 								  &gen_event);
266 			pr_debug("slave: %d, port: %d prev_port_state: %d,"
267 				 " new_port_state: %d, gen_event: %d\n",
268 				 slave_id, port_num, prev_state, new_state, gen_event);
269 			if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
270 				pr_debug("sending PORT_UP event to slave: %d, port: %d\n",
271 					 slave_id, port_num);
272 				mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
273 							       port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
274 			}
275 		} else { /* request to invalidate GUID */
276 			set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
277 						      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
278 						      &gen_event);
279 			if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) {
280 				pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
281 					 slave_id, port_num);
282 				mlx4_gen_port_state_change_eqe(dev->dev,
283 							       slave_id,
284 							       port_num,
285 							       MLX4_PORT_CHANGE_SUBTYPE_DOWN);
286 			}
287 		}
288 	}
289 }
290 
aliasguid_query_handler(int status,struct ib_sa_guidinfo_rec * guid_rec,void * context)291 static void aliasguid_query_handler(int status,
292 				    struct ib_sa_guidinfo_rec *guid_rec,
293 				    void *context)
294 {
295 	struct mlx4_ib_dev *dev;
296 	struct mlx4_alias_guid_work_context *cb_ctx = context;
297 	u8 port_index;
298 	int i;
299 	struct mlx4_sriov_alias_guid_info_rec_det *rec;
300 	unsigned long flags, flags1;
301 	ib_sa_comp_mask declined_guid_indexes = 0;
302 	ib_sa_comp_mask applied_guid_indexes = 0;
303 	unsigned int resched_delay_sec = 0;
304 
305 	if (!context)
306 		return;
307 
308 	dev = cb_ctx->dev;
309 	port_index = cb_ctx->port - 1;
310 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
311 		all_rec_per_port[cb_ctx->block_num];
312 
313 	if (status) {
314 		pr_debug("(port: %d) failed: status = %d\n",
315 			 cb_ctx->port, status);
316 		rec->time_to_run = ktime_get_ns() + 1 * NSEC_PER_SEC;
317 		goto out;
318 	}
319 
320 	if (guid_rec->block_num != cb_ctx->block_num) {
321 		pr_err("block num mismatch: %d != %d\n",
322 		       cb_ctx->block_num, guid_rec->block_num);
323 		goto out;
324 	}
325 
326 	pr_debug("lid/port: %d/%d, block_num: %d\n",
327 		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
328 		 guid_rec->block_num);
329 
330 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
331 		all_rec_per_port[guid_rec->block_num];
332 
333 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
334 	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
335 		__be64 sm_response, required_val;
336 
337 		if (!(cb_ctx->guid_indexes &
338 			mlx4_ib_get_aguid_comp_mask_from_ix(i)))
339 			continue;
340 		sm_response = *(__be64 *)&guid_rec->guid_info_list
341 				[i * GUID_REC_SIZE];
342 		required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
343 		if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) {
344 			if (required_val ==
345 			    cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
346 				goto next_entry;
347 
348 			/* A new value was set till we got the response */
349 			pr_debug("need to set new value %llx, record num %d, block_num:%d\n",
350 				 (long long)be64_to_cpu(required_val),
351 				 i, guid_rec->block_num);
352 			goto entry_declined;
353 		}
354 
355 		/* check if the SM didn't assign one of the records.
356 		 * if it didn't, re-ask for.
357 		 */
358 		if (sm_response == MLX4_NOT_SET_GUID) {
359 			if (rec->guids_retry_schedule[i] == 0)
360 				mlx4_ib_warn(&dev->ib_dev,
361 					     "%s:Record num %d in  block_num: %d was declined by SM\n",
362 					     __func__, i,
363 					     guid_rec->block_num);
364 			goto entry_declined;
365 		} else {
366 		       /* properly assigned record. */
367 		       /* We save the GUID we just got from the SM in the
368 			* admin_guid in order to be persistent, and in the
369 			* request from the sm the process will ask for the same GUID */
370 			if (required_val &&
371 			    sm_response != required_val) {
372 				/* Warn only on first retry */
373 				if (rec->guids_retry_schedule[i] == 0)
374 					mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
375 						     " admin guid after SysAdmin "
376 						     "configuration. "
377 						     "Record num %d in block_num:%d "
378 						     "was declined by SM, "
379 						     "new val(0x%llx) was kept, SM returned (0x%llx)\n",
380 						      __func__, i,
381 						     guid_rec->block_num,
382 						     (long long)be64_to_cpu(required_val),
383 						     (long long)be64_to_cpu(sm_response));
384 				goto entry_declined;
385 			} else {
386 				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
387 					sm_response;
388 				if (required_val == 0)
389 					mlx4_set_admin_guid(dev->dev,
390 							    sm_response,
391 							    (guid_rec->block_num
392 							    * NUM_ALIAS_GUID_IN_REC) + i,
393 							    cb_ctx->port);
394 				goto next_entry;
395 			}
396 		}
397 entry_declined:
398 		declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
399 		rec->guids_retry_schedule[i] =
400 			(rec->guids_retry_schedule[i] == 0) ?  1 :
401 			min((unsigned int)60,
402 			    rec->guids_retry_schedule[i] * 2);
403 		/* using the minimum value among all entries in that record */
404 		resched_delay_sec = (resched_delay_sec == 0) ?
405 				rec->guids_retry_schedule[i] :
406 				min(resched_delay_sec,
407 				    rec->guids_retry_schedule[i]);
408 		continue;
409 
410 next_entry:
411 		rec->guids_retry_schedule[i] = 0;
412 	}
413 
414 	applied_guid_indexes =  cb_ctx->guid_indexes & ~declined_guid_indexes;
415 	if (declined_guid_indexes ||
416 	    rec->guid_indexes & ~(applied_guid_indexes)) {
417 		pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n",
418 			 guid_rec->block_num,
419 			 (long long)be64_to_cpu((__force __be64)rec->guid_indexes),
420 			 (long long)be64_to_cpu((__force __be64)applied_guid_indexes),
421 			 (long long)be64_to_cpu((__force __be64)declined_guid_indexes));
422 		rec->time_to_run = ktime_get_ns() +
423 			resched_delay_sec * NSEC_PER_SEC;
424 	} else {
425 		rec->status = MLX4_GUID_INFO_STATUS_SET;
426 	}
427 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
428 	/*
429 	The func is call here to close the cases when the
430 	sm doesn't send smp, so in the sa response the driver
431 	notifies the slave.
432 	*/
433 	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
434 					     cb_ctx->port,
435 					     guid_rec->guid_info_list);
436 out:
437 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
438 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
439 	if (!dev->sriov.is_going_down) {
440 		get_low_record_time_index(dev, port_index, &resched_delay_sec);
441 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
442 				   &dev->sriov.alias_guid.ports_guid[port_index].
443 				   alias_guid_work,
444 				   msecs_to_jiffies(resched_delay_sec * 1000));
445 	}
446 	if (cb_ctx->sa_query) {
447 		list_del(&cb_ctx->list);
448 		kfree(cb_ctx);
449 	} else
450 		complete(&cb_ctx->done);
451 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
452 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
453 }
454 
invalidate_guid_record(struct mlx4_ib_dev * dev,u8 port,int index)455 static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
456 {
457 	int i;
458 	u64 cur_admin_val;
459 	ib_sa_comp_mask comp_mask = 0;
460 
461 	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
462 		= MLX4_GUID_INFO_STATUS_SET;
463 
464 	/* calculate the comp_mask for that record.*/
465 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
466 		cur_admin_val =
467 			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
468 			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
469 		/*
470 		check the admin value: if it's for delete (~00LL) or
471 		it is the first guid of the first record (hw guid) or
472 		the records is not in ownership of the sysadmin and the sm doesn't
473 		need to assign GUIDs, then don't put it up for assignment.
474 		*/
475 		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
476 		    (!index && !i))
477 			continue;
478 		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
479 	}
480 	dev->sriov.alias_guid.ports_guid[port - 1].
481 		all_rec_per_port[index].guid_indexes |= comp_mask;
482 	if (dev->sriov.alias_guid.ports_guid[port - 1].
483 	    all_rec_per_port[index].guid_indexes)
484 		dev->sriov.alias_guid.ports_guid[port - 1].
485 		all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE;
486 
487 }
488 
set_guid_rec(struct ib_device * ibdev,struct mlx4_next_alias_guid_work * rec)489 static int set_guid_rec(struct ib_device *ibdev,
490 			struct mlx4_next_alias_guid_work *rec)
491 {
492 	int err;
493 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
494 	struct ib_sa_guidinfo_rec guid_info_rec;
495 	ib_sa_comp_mask comp_mask;
496 	struct ib_port_attr attr;
497 	struct mlx4_alias_guid_work_context *callback_context;
498 	unsigned long resched_delay, flags, flags1;
499 	u8 port = rec->port + 1;
500 	int index = rec->block_num;
501 	struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det;
502 	struct list_head *head =
503 		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
504 
505 	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
506 	if (err) {
507 		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
508 			 err, port);
509 		return err;
510 	}
511 	/*check the port was configured by the sm, otherwise no need to send */
512 	if (attr.state != IB_PORT_ACTIVE) {
513 		pr_debug("port %d not active...rescheduling\n", port);
514 		resched_delay = 5 * HZ;
515 		err = -EAGAIN;
516 		goto new_schedule;
517 	}
518 
519 	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
520 	if (!callback_context) {
521 		err = -ENOMEM;
522 		resched_delay = HZ * 5;
523 		goto new_schedule;
524 	}
525 	callback_context->port = port;
526 	callback_context->dev = dev;
527 	callback_context->block_num = index;
528 	callback_context->guid_indexes = rec_det->guid_indexes;
529 	callback_context->method = rec->method;
530 
531 	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
532 
533 	guid_info_rec.lid = cpu_to_be16(attr.lid);
534 	guid_info_rec.block_num = index;
535 
536 	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
537 	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
538 	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
539 		rec_det->guid_indexes;
540 
541 	init_completion(&callback_context->done);
542 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
543 	list_add_tail(&callback_context->list, head);
544 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
545 
546 	callback_context->query_id =
547 		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
548 					  ibdev, port, &guid_info_rec,
549 					  comp_mask, rec->method, 1000,
550 					  GFP_KERNEL, aliasguid_query_handler,
551 					  callback_context,
552 					  &callback_context->sa_query);
553 	if (callback_context->query_id < 0) {
554 		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
555 			 "%d. will reschedule to the next 1 sec.\n",
556 			 callback_context->query_id);
557 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
558 		list_del(&callback_context->list);
559 		kfree(callback_context);
560 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
561 		resched_delay = 1 * HZ;
562 		err = -EAGAIN;
563 		goto new_schedule;
564 	}
565 	err = 0;
566 	goto out;
567 
568 new_schedule:
569 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
570 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
571 	invalidate_guid_record(dev, port, index);
572 	if (!dev->sriov.is_going_down) {
573 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
574 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
575 				   resched_delay);
576 	}
577 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
578 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
579 
580 out:
581 	return err;
582 }
583 
mlx4_ib_guid_port_init(struct mlx4_ib_dev * dev,int port)584 static void mlx4_ib_guid_port_init(struct mlx4_ib_dev *dev, int port)
585 {
586 	int j, k, entry;
587 	__be64 guid;
588 
589 	/*Check if the SM doesn't need to assign the GUIDs*/
590 	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
591 		for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
592 			entry = j * NUM_ALIAS_GUID_IN_REC + k;
593 			/* no request for the 0 entry (hw guid) */
594 			if (!entry || entry > dev->dev->persist->num_vfs ||
595 			    !mlx4_is_slave_active(dev->dev, entry))
596 				continue;
597 			guid = mlx4_get_admin_guid(dev->dev, entry, port);
598 			*(__be64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
599 				all_rec_per_port[j].all_recs
600 				[GUID_REC_SIZE * k] = guid;
601 			pr_debug("guid was set, entry=%d, val=0x%llx, port=%d\n",
602 				 entry,
603 				 (long long)be64_to_cpu(guid),
604 				 port);
605 		}
606 	}
607 }
mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev * dev,int port)608 void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
609 {
610 	int i;
611 	unsigned long flags, flags1;
612 
613 	pr_debug("port %d\n", port);
614 
615 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
616 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
617 
618 	if (dev->sriov.alias_guid.ports_guid[port - 1].state_flags &
619 		GUID_STATE_NEED_PORT_INIT) {
620 		mlx4_ib_guid_port_init(dev, port);
621 		dev->sriov.alias_guid.ports_guid[port - 1].state_flags &=
622 			(~GUID_STATE_NEED_PORT_INIT);
623 	}
624 	for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
625 		invalidate_guid_record(dev, port, i);
626 
627 	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
628 		/*
629 		make sure no work waits in the queue, if the work is already
630 		queued(not on the timer) the cancel will fail. That is not a problem
631 		because we just want the work started.
632 		*/
633 		cancel_delayed_work(&dev->sriov.alias_guid.
634 				      ports_guid[port - 1].alias_guid_work);
635 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
636 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
637 				   0);
638 	}
639 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
640 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
641 }
642 
set_required_record(struct mlx4_ib_dev * dev,u8 port,struct mlx4_next_alias_guid_work * next_rec,int record_index)643 static void set_required_record(struct mlx4_ib_dev *dev, u8 port,
644 				struct mlx4_next_alias_guid_work *next_rec,
645 				int record_index)
646 {
647 	int i;
648 	int lowset_time_entry = -1;
649 	int lowest_time = 0;
650 	ib_sa_comp_mask delete_guid_indexes = 0;
651 	ib_sa_comp_mask set_guid_indexes = 0;
652 	struct mlx4_sriov_alias_guid_info_rec_det *rec =
653 			&dev->sriov.alias_guid.ports_guid[port].
654 			all_rec_per_port[record_index];
655 
656 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
657 		if (!(rec->guid_indexes &
658 			mlx4_ib_get_aguid_comp_mask_from_ix(i)))
659 			continue;
660 
661 		if (*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] ==
662 				cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
663 			delete_guid_indexes |=
664 				mlx4_ib_get_aguid_comp_mask_from_ix(i);
665 		else
666 			set_guid_indexes |=
667 				mlx4_ib_get_aguid_comp_mask_from_ix(i);
668 
669 		if (lowset_time_entry == -1 || rec->guids_retry_schedule[i] <=
670 			lowest_time) {
671 			lowset_time_entry = i;
672 			lowest_time = rec->guids_retry_schedule[i];
673 		}
674 	}
675 
676 	memcpy(&next_rec->rec_det, rec, sizeof(*rec));
677 	next_rec->port = port;
678 	next_rec->block_num = record_index;
679 
680 	if (*(__be64 *)&rec->all_recs[lowset_time_entry * GUID_REC_SIZE] ==
681 				cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) {
682 		next_rec->rec_det.guid_indexes = delete_guid_indexes;
683 		next_rec->method = MLX4_GUID_INFO_RECORD_DELETE;
684 	} else {
685 		next_rec->rec_det.guid_indexes = set_guid_indexes;
686 		next_rec->method = MLX4_GUID_INFO_RECORD_SET;
687 	}
688 }
689 
690 /* return index of record that should be updated based on lowest
691  * rescheduled time
692  */
get_low_record_time_index(struct mlx4_ib_dev * dev,u8 port,int * resched_delay_sec)693 static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
694 				     int *resched_delay_sec)
695 {
696 	int record_index = -1;
697 	u64 low_record_time = 0;
698 	struct mlx4_sriov_alias_guid_info_rec_det rec;
699 	int j;
700 
701 	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
702 		rec = dev->sriov.alias_guid.ports_guid[port].
703 			all_rec_per_port[j];
704 		if (rec.status == MLX4_GUID_INFO_STATUS_IDLE &&
705 		    rec.guid_indexes) {
706 			if (record_index == -1 ||
707 			    rec.time_to_run < low_record_time) {
708 				record_index = j;
709 				low_record_time = rec.time_to_run;
710 			}
711 		}
712 	}
713 	if (resched_delay_sec) {
714 		u64 curr_time = ktime_get_ns();
715 
716 		*resched_delay_sec = (low_record_time < curr_time) ? 0 :
717 			div_u64((low_record_time - curr_time), NSEC_PER_SEC);
718 	}
719 
720 	return record_index;
721 }
722 
723 /* The function returns the next record that was
724  * 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)725 static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
726 				     struct mlx4_next_alias_guid_work *rec)
727 {
728 	unsigned long flags;
729 	int record_index;
730 	int ret = 0;
731 
732 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
733 	record_index = get_low_record_time_index(dev, port, NULL);
734 
735 	if (record_index < 0) {
736 		ret = -ENOENT;
737 		goto out;
738 	}
739 
740 	set_required_record(dev, port, rec, record_index);
741 out:
742 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
743 	return ret;
744 }
745 
alias_guid_work(struct work_struct * work)746 static void alias_guid_work(struct work_struct *work)
747 {
748 	struct delayed_work *delay = to_delayed_work(work);
749 	int ret = 0;
750 	struct mlx4_next_alias_guid_work *rec;
751 	struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
752 		container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
753 			     alias_guid_work);
754 	struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
755 	struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
756 						struct mlx4_ib_sriov,
757 						alias_guid);
758 	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
759 
760 	rec = kzalloc(sizeof *rec, GFP_KERNEL);
761 	if (!rec) {
762 		pr_err("alias_guid_work: No Memory\n");
763 		return;
764 	}
765 
766 	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
767 	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
768 	if (ret) {
769 		pr_debug("No more records to update.\n");
770 		goto out;
771 	}
772 
773 	set_guid_rec(&dev->ib_dev, rec);
774 out:
775 	kfree(rec);
776 }
777 
778 
mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev * dev,int port)779 void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
780 {
781 	unsigned long flags, flags1;
782 
783 	if (!mlx4_is_master(dev->dev))
784 		return;
785 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
786 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
787 	if (!dev->sriov.is_going_down) {
788 		/* If there is pending one should cancell then run, otherwise
789 		  * won't run till previous one is ended as same work
790 		  * struct is used.
791 		  */
792 		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port].
793 				    alias_guid_work);
794 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
795 			   &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
796 	}
797 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
798 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
799 }
800 
mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev * dev)801 void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
802 {
803 	int i;
804 	struct mlx4_ib_sriov *sriov = &dev->sriov;
805 	struct mlx4_alias_guid_work_context *cb_ctx;
806 	struct mlx4_sriov_alias_guid_port_rec_det *det;
807 	struct ib_sa_query *sa_query;
808 	unsigned long flags;
809 
810 	for (i = 0 ; i < dev->num_ports; i++) {
811 		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
812 		det = &sriov->alias_guid.ports_guid[i];
813 		spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
814 		while (!list_empty(&det->cb_list)) {
815 			cb_ctx = list_entry(det->cb_list.next,
816 					    struct mlx4_alias_guid_work_context,
817 					    list);
818 			sa_query = cb_ctx->sa_query;
819 			cb_ctx->sa_query = NULL;
820 			list_del(&cb_ctx->list);
821 			spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
822 			ib_sa_cancel_query(cb_ctx->query_id, sa_query);
823 			wait_for_completion(&cb_ctx->done);
824 			kfree(cb_ctx);
825 			spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
826 		}
827 		spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
828 	}
829 	for (i = 0 ; i < dev->num_ports; i++) {
830 		flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
831 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
832 	}
833 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
834 	kfree(dev->sriov.alias_guid.sa_client);
835 }
836 
mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev * dev)837 int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
838 {
839 	char alias_wq_name[15];
840 	int ret = 0;
841 	int i, j;
842 	union ib_gid gid;
843 
844 	if (!mlx4_is_master(dev->dev))
845 		return 0;
846 	dev->sriov.alias_guid.sa_client =
847 		kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
848 	if (!dev->sriov.alias_guid.sa_client)
849 		return -ENOMEM;
850 
851 	ib_sa_register_client(dev->sriov.alias_guid.sa_client);
852 
853 	spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
854 
855 	for (i = 1; i <= dev->num_ports; ++i) {
856 		if (dev->ib_dev.query_gid(&dev->ib_dev , i, 0, &gid)) {
857 			ret = -EFAULT;
858 			goto err_unregister;
859 		}
860 	}
861 
862 	for (i = 0 ; i < dev->num_ports; i++) {
863 		memset(&dev->sriov.alias_guid.ports_guid[i], 0,
864 		       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
865 		dev->sriov.alias_guid.ports_guid[i].state_flags |=
866 				GUID_STATE_NEED_PORT_INIT;
867 		for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
868 			/* mark each val as it was deleted */
869 			memset(dev->sriov.alias_guid.ports_guid[i].
870 				all_rec_per_port[j].all_recs, 0xFF,
871 				sizeof(dev->sriov.alias_guid.ports_guid[i].
872 				all_rec_per_port[j].all_recs));
873 		}
874 		INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
875 		/*prepare the records, set them to be allocated by sm*/
876 		if (mlx4_ib_sm_guid_assign)
877 			for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
878 				mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
879 		for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
880 			invalidate_guid_record(dev, i + 1, j);
881 
882 		dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
883 		dev->sriov.alias_guid.ports_guid[i].port  = i;
884 
885 		snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
886 		dev->sriov.alias_guid.ports_guid[i].wq =
887 			alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
888 		if (!dev->sriov.alias_guid.ports_guid[i].wq) {
889 			ret = -ENOMEM;
890 			goto err_thread;
891 		}
892 		INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
893 			  alias_guid_work);
894 	}
895 	return 0;
896 
897 err_thread:
898 	for (--i; i >= 0; i--) {
899 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
900 		dev->sriov.alias_guid.ports_guid[i].wq = NULL;
901 	}
902 
903 err_unregister:
904 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
905 	kfree(dev->sriov.alias_guid.sa_client);
906 	dev->sriov.alias_guid.sa_client = NULL;
907 	pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
908 	return ret;
909 }
910