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