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