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/init.h>
42#include <linux/errno.h>
43#include <rdma/ib_user_verbs.h>
44#include <linux/delay.h>
45#include "mlx4_ib.h"
46
47/*
48The driver keeps the current state of all guids, as they are in the HW.
49Whenever we receive an smp mad GUIDInfo record, the data will be cached.
50*/
51
52struct mlx4_alias_guid_work_context {
53 u8 port;
54 struct mlx4_ib_dev *dev ;
55 struct ib_sa_query *sa_query;
56 struct completion done;
57 int query_id;
58 struct list_head list;
59 int block_num;
60 ib_sa_comp_mask guid_indexes;
61 u8 method;
62};
63
64struct mlx4_next_alias_guid_work {
65 u8 port;
66 u8 block_num;
67 u8 method;
68 struct mlx4_sriov_alias_guid_info_rec_det rec_det;
69};
70
71static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
72 int *resched_delay_sec);
73
74void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
75 u32 port_num, u8 *p_data)
76{
77 int i;
78 u64 guid_indexes;
79 int slave_id;
80 u32 port_index = port_num - 1;
81
82 if (!mlx4_is_master(dev: dev->dev))
83 return;
84
85 guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
86 ports_guid[port_num - 1].
87 all_rec_per_port[block_num].guid_indexes);
88 pr_debug("port: %u, guid_indexes: 0x%llx\n", port_num, guid_indexes);
89
90 for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
91 /* The location of the specific index starts from bit number 4
92 * until bit num 11 */
93 if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
94 slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
95 if (slave_id >= dev->dev->num_slaves) {
96 pr_debug("The last slave: %d\n", slave_id);
97 return;
98 }
99
100 /* cache the guid: */
101 memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
102 &p_data[i * GUID_REC_SIZE],
103 GUID_REC_SIZE);
104 } else
105 pr_debug("Guid number: %d in block: %d"
106 " was not updated\n", i, block_num);
107 }
108}
109
110static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
111{
112 if (index >= NUM_ALIAS_GUID_PER_PORT) {
113 pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
114 return (__force __be64) -1;
115 }
116 return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
117}
118
119
120ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
121{
122 return IB_SA_COMP_MASK(4 + index);
123}
124
125void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
126 int port, int slave_init)
127{
128 __be64 curr_guid, required_guid;
129 int record_num = slave / 8;
130 int index = slave % 8;
131 int port_index = port - 1;
132 unsigned long flags;
133 int do_work = 0;
134
135 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
136 if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
137 GUID_STATE_NEED_PORT_INIT)
138 goto unlock;
139 if (!slave_init) {
140 curr_guid = *(__be64 *)&dev->sriov.
141 alias_guid.ports_guid[port_index].
142 all_rec_per_port[record_num].
143 all_recs[GUID_REC_SIZE * index];
144 if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
145 !curr_guid)
146 goto unlock;
147 required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
148 } else {
149 required_guid = mlx4_get_admin_guid(dev: dev->dev, entry: slave, port);
150 if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
151 goto unlock;
152 }
153 *(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
154 all_rec_per_port[record_num].
155 all_recs[GUID_REC_SIZE * index] = required_guid;
156 dev->sriov.alias_guid.ports_guid[port_index].
157 all_rec_per_port[record_num].guid_indexes
158 |= mlx4_ib_get_aguid_comp_mask_from_ix(index);
159 dev->sriov.alias_guid.ports_guid[port_index].
160 all_rec_per_port[record_num].status
161 = MLX4_GUID_INFO_STATUS_IDLE;
162 /* set to run immediately */
163 dev->sriov.alias_guid.ports_guid[port_index].
164 all_rec_per_port[record_num].time_to_run = 0;
165 dev->sriov.alias_guid.ports_guid[port_index].
166 all_rec_per_port[record_num].
167 guids_retry_schedule[index] = 0;
168 do_work = 1;
169unlock:
170 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags);
171
172 if (do_work)
173 mlx4_ib_init_alias_guid_work(dev, port: port_index);
174}
175
176/*
177 * Whenever new GUID is set/unset (guid table change) create event and
178 * notify the relevant slave (master also should be notified).
179 * If the GUID value is not as we have in the cache the slave will not be
180 * updated; in this case it waits for the smp_snoop or the port management
181 * event to call the function and to update the slave.
182 * block_number - the index of the block (16 blocks available)
183 * port_number - 1 or 2
184 */
185void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
186 int block_num, u32 port_num,
187 u8 *p_data)
188{
189 int i;
190 u64 guid_indexes;
191 int slave_id, slave_port;
192 enum slave_port_state new_state;
193 enum slave_port_state prev_state;
194 __be64 tmp_cur_ag, form_cache_ag;
195 enum slave_port_gen_event gen_event;
196 struct mlx4_sriov_alias_guid_info_rec_det *rec;
197 unsigned long flags;
198 __be64 required_value;
199
200 if (!mlx4_is_master(dev: dev->dev))
201 return;
202
203 rec = &dev->sriov.alias_guid.ports_guid[port_num - 1].
204 all_rec_per_port[block_num];
205 guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
206 ports_guid[port_num - 1].
207 all_rec_per_port[block_num].guid_indexes);
208 pr_debug("port: %u, guid_indexes: 0x%llx\n", port_num, guid_indexes);
209
210 /*calculate the slaves and notify them*/
211 for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
212 /* the location of the specific index runs from bits 4..11 */
213 if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
214 continue;
215
216 slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
217 if (slave_id >= dev->dev->persist->num_vfs + 1)
218 return;
219
220 slave_port = mlx4_phys_to_slave_port(dev: dev->dev, slave: slave_id, port: port_num);
221 if (slave_port < 0) /* this port isn't available for the VF */
222 continue;
223
224 tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
225 form_cache_ag = get_cached_alias_guid(dev, port: port_num,
226 index: (NUM_ALIAS_GUID_IN_REC * block_num) + i);
227 /*
228 * Check if guid is not the same as in the cache,
229 * If it is different, wait for the snoop_smp or the port mgmt
230 * change event to update the slave on its port state change
231 */
232 if (tmp_cur_ag != form_cache_ag)
233 continue;
234
235 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
236 required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
237
238 if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
239 required_value = 0;
240
241 if (tmp_cur_ag == required_value) {
242 rec->guid_indexes = rec->guid_indexes &
243 ~mlx4_ib_get_aguid_comp_mask_from_ix(index: i);
244 } else {
245 /* may notify port down if value is 0 */
246 if (tmp_cur_ag != MLX4_NOT_SET_GUID) {
247 spin_unlock_irqrestore(lock: &dev->sriov.
248 alias_guid.ag_work_lock, flags);
249 continue;
250 }
251 }
252 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock,
253 flags);
254 mlx4_gen_guid_change_eqe(dev: dev->dev, slave: slave_id, port: port_num);
255 /*2 cases: Valid GUID, and Invalid Guid*/
256
257 if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
258 prev_state = mlx4_get_slave_port_state(dev: dev->dev, slave: slave_id, port: port_num);
259 new_state = set_and_calc_slave_port_state(dev: dev->dev, slave: slave_id, port: port_num,
260 event: MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
261 gen_event: &gen_event);
262 pr_debug("slave: %d, port: %u prev_port_state: %d,"
263 " new_port_state: %d, gen_event: %d\n",
264 slave_id, port_num, prev_state, new_state, gen_event);
265 if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
266 pr_debug("sending PORT_UP event to slave: %d, port: %u\n",
267 slave_id, port_num);
268 mlx4_gen_port_state_change_eqe(dev: dev->dev, slave: slave_id,
269 port: port_num, port_subtype_change: MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
270 }
271 } else { /* request to invalidate GUID */
272 set_and_calc_slave_port_state(dev: dev->dev, slave: slave_id, port: port_num,
273 event: MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
274 gen_event: &gen_event);
275 if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) {
276 pr_debug("sending PORT DOWN event to slave: %d, port: %u\n",
277 slave_id, port_num);
278 mlx4_gen_port_state_change_eqe(dev: dev->dev,
279 slave: slave_id,
280 port: port_num,
281 port_subtype_change: MLX4_PORT_CHANGE_SUBTYPE_DOWN);
282 }
283 }
284 }
285}
286
287static void aliasguid_query_handler(int status,
288 struct ib_sa_guidinfo_rec *guid_rec,
289 void *context)
290{
291 struct mlx4_ib_dev *dev;
292 struct mlx4_alias_guid_work_context *cb_ctx = context;
293 u8 port_index ;
294 int i;
295 struct mlx4_sriov_alias_guid_info_rec_det *rec;
296 unsigned long flags, flags1;
297 ib_sa_comp_mask declined_guid_indexes = 0;
298 ib_sa_comp_mask applied_guid_indexes = 0;
299 unsigned int resched_delay_sec = 0;
300
301 if (!context)
302 return;
303
304 dev = cb_ctx->dev;
305 port_index = cb_ctx->port - 1;
306 rec = &dev->sriov.alias_guid.ports_guid[port_index].
307 all_rec_per_port[cb_ctx->block_num];
308
309 if (status) {
310 pr_debug("(port: %d) failed: status = %d\n",
311 cb_ctx->port, status);
312 rec->time_to_run = ktime_get_boottime_ns() + 1 * NSEC_PER_SEC;
313 goto out;
314 }
315
316 if (guid_rec->block_num != cb_ctx->block_num) {
317 pr_err("block num mismatch: %d != %d\n",
318 cb_ctx->block_num, guid_rec->block_num);
319 goto out;
320 }
321
322 pr_debug("lid/port: %d/%d, block_num: %d\n",
323 be16_to_cpu(guid_rec->lid), cb_ctx->port,
324 guid_rec->block_num);
325
326 rec = &dev->sriov.alias_guid.ports_guid[port_index].
327 all_rec_per_port[guid_rec->block_num];
328
329 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
330 for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
331 __be64 sm_response, required_val;
332
333 if (!(cb_ctx->guid_indexes &
334 mlx4_ib_get_aguid_comp_mask_from_ix(index: i)))
335 continue;
336 sm_response = *(__be64 *)&guid_rec->guid_info_list
337 [i * GUID_REC_SIZE];
338 required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
339 if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) {
340 if (required_val ==
341 cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
342 goto next_entry;
343
344 /* A new value was set till we got the response */
345 pr_debug("need to set new value %llx, record num %d, block_num:%d\n",
346 be64_to_cpu(required_val),
347 i, guid_rec->block_num);
348 goto entry_declined;
349 }
350
351 /* check if the SM didn't assign one of the records.
352 * if it didn't, re-ask for.
353 */
354 if (sm_response == MLX4_NOT_SET_GUID) {
355 if (rec->guids_retry_schedule[i] == 0)
356 mlx4_ib_warn(&dev->ib_dev,
357 "%s:Record num %d in block_num: %d was declined by SM\n",
358 __func__, i,
359 guid_rec->block_num);
360 goto entry_declined;
361 } else {
362 /* properly assigned record. */
363 /* We save the GUID we just got from the SM in the
364 * admin_guid in order to be persistent, and in the
365 * request from the sm the process will ask for the same GUID */
366 if (required_val &&
367 sm_response != required_val) {
368 /* Warn only on first retry */
369 if (rec->guids_retry_schedule[i] == 0)
370 mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
371 " admin guid after SysAdmin "
372 "configuration. "
373 "Record num %d in block_num:%d "
374 "was declined by SM, "
375 "new val(0x%llx) was kept, SM returned (0x%llx)\n",
376 __func__, i,
377 guid_rec->block_num,
378 be64_to_cpu(required_val),
379 be64_to_cpu(sm_response));
380 goto entry_declined;
381 } else {
382 *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
383 sm_response;
384 if (required_val == 0)
385 mlx4_set_admin_guid(dev: dev->dev,
386 guid: sm_response,
387 entry: (guid_rec->block_num
388 * NUM_ALIAS_GUID_IN_REC) + i,
389 port: cb_ctx->port);
390 goto next_entry;
391 }
392 }
393entry_declined:
394 declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(index: i);
395 rec->guids_retry_schedule[i] =
396 (rec->guids_retry_schedule[i] == 0) ? 1 :
397 min((unsigned int)60,
398 rec->guids_retry_schedule[i] * 2);
399 /* using the minimum value among all entries in that record */
400 resched_delay_sec = (resched_delay_sec == 0) ?
401 rec->guids_retry_schedule[i] :
402 min(resched_delay_sec,
403 rec->guids_retry_schedule[i]);
404 continue;
405
406next_entry:
407 rec->guids_retry_schedule[i] = 0;
408 }
409
410 applied_guid_indexes = cb_ctx->guid_indexes & ~declined_guid_indexes;
411 if (declined_guid_indexes ||
412 rec->guid_indexes & ~(applied_guid_indexes)) {
413 pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n",
414 guid_rec->block_num,
415 be64_to_cpu((__force __be64)rec->guid_indexes),
416 be64_to_cpu((__force __be64)applied_guid_indexes),
417 be64_to_cpu((__force __be64)declined_guid_indexes));
418 rec->time_to_run = ktime_get_boottime_ns() +
419 resched_delay_sec * NSEC_PER_SEC;
420 } else {
421 rec->status = MLX4_GUID_INFO_STATUS_SET;
422 }
423 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags);
424 /*
425 The func is call here to close the cases when the
426 sm doesn't send smp, so in the sa response the driver
427 notifies the slave.
428 */
429 mlx4_ib_notify_slaves_on_guid_change(dev, block_num: guid_rec->block_num,
430 port_num: cb_ctx->port,
431 p_data: guid_rec->guid_info_list);
432out:
433 spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
434 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
435 if (!dev->sriov.is_going_down) {
436 get_low_record_time_index(dev, port: port_index, resched_delay_sec: &resched_delay_sec);
437 queue_delayed_work(wq: dev->sriov.alias_guid.ports_guid[port_index].wq,
438 dwork: &dev->sriov.alias_guid.ports_guid[port_index].
439 alias_guid_work,
440 delay: msecs_to_jiffies(m: resched_delay_sec * 1000));
441 }
442 if (cb_ctx->sa_query) {
443 list_del(entry: &cb_ctx->list);
444 kfree(objp: cb_ctx);
445 } else
446 complete(&cb_ctx->done);
447 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
448 spin_unlock_irqrestore(lock: &dev->sriov.going_down_lock, flags);
449}
450
451static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
452{
453 int i;
454 u64 cur_admin_val;
455 ib_sa_comp_mask comp_mask = 0;
456
457 dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
458 = MLX4_GUID_INFO_STATUS_SET;
459
460 /* calculate the comp_mask for that record.*/
461 for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
462 cur_admin_val =
463 *(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
464 all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
465 /*
466 check the admin value: if it's for delete (~00LL) or
467 it is the first guid of the first record (hw guid) or
468 the records is not in ownership of the sysadmin and the sm doesn't
469 need to assign GUIDs, then don't put it up for assignment.
470 */
471 if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
472 (!index && !i))
473 continue;
474 comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(index: i);
475 }
476 dev->sriov.alias_guid.ports_guid[port - 1].
477 all_rec_per_port[index].guid_indexes |= comp_mask;
478 if (dev->sriov.alias_guid.ports_guid[port - 1].
479 all_rec_per_port[index].guid_indexes)
480 dev->sriov.alias_guid.ports_guid[port - 1].
481 all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE;
482
483}
484
485static int set_guid_rec(struct ib_device *ibdev,
486 struct mlx4_next_alias_guid_work *rec)
487{
488 int err;
489 struct mlx4_ib_dev *dev = to_mdev(ibdev);
490 struct ib_sa_guidinfo_rec guid_info_rec;
491 ib_sa_comp_mask comp_mask;
492 struct ib_port_attr attr;
493 struct mlx4_alias_guid_work_context *callback_context;
494 unsigned long resched_delay, flags, flags1;
495 u8 port = rec->port + 1;
496 int index = rec->block_num;
497 struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det;
498 struct list_head *head =
499 &dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
500
501 memset(&attr, 0, sizeof(attr));
502 err = __mlx4_ib_query_port(ibdev, port, props: &attr, netw_view: 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(size: 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 = ib_lid_be16(lid: 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(x: &callback_context->done);
539 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
540 list_add_tail(new: &callback_context->list, head);
541 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
542
543 callback_context->query_id =
544 ib_sa_guid_info_rec_query(client: dev->sriov.alias_guid.sa_client,
545 device: ibdev, port_num: port, rec: &guid_info_rec,
546 comp_mask, method: rec->method, timeout_ms: 1000,
547 GFP_KERNEL, callback: aliasguid_query_handler,
548 context: callback_context,
549 sa_query: &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(entry: &callback_context->list);
556 kfree(objp: callback_context);
557 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
558 resched_delay = 1 * HZ;
559 err = -EAGAIN;
560 goto new_schedule;
561 }
562 err = 0;
563 goto out;
564
565new_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(wq: dev->sriov.alias_guid.ports_guid[port - 1].wq,
571 dwork: &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
572 delay: resched_delay);
573 }
574 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
575 spin_unlock_irqrestore(lock: &dev->sriov.going_down_lock, flags);
576
577out:
578 return err;
579}
580
581static 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->dev, slave: entry))
593 continue;
594 guid = mlx4_get_admin_guid(dev: 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}
605void 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, index: i);
623
624 if (mlx4_is_master(dev: 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(dwork: &dev->sriov.alias_guid.
631 ports_guid[port - 1].alias_guid_work);
632 queue_delayed_work(wq: dev->sriov.alias_guid.ports_guid[port - 1].wq,
633 dwork: &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
634 delay: 0);
635 }
636 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
637 spin_unlock_irqrestore(lock: &dev->sriov.going_down_lock, flags);
638}
639
640static 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(index: 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(index: i);
662 else
663 set_guid_indexes |=
664 mlx4_ib_get_aguid_comp_mask_from_ix(index: 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 */
690static 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_boottime_ns();
712
713 *resched_delay_sec = (low_record_time < curr_time) ? 0 :
714 div_u64(dividend: (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) */
722static 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, next_rec: rec, record_index);
738out:
739 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags);
740 return ret;
741}
742
743static 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(size: sizeof *rec, GFP_KERNEL);
758 if (!rec)
759 return;
760
761 pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
762 ret = get_next_record_to_update(dev, port: sriov_alias_port->port, rec);
763 if (ret) {
764 pr_debug("No more records to update.\n");
765 goto out;
766 }
767
768 set_guid_rec(ibdev: &dev->ib_dev, rec);
769out:
770 kfree(objp: rec);
771}
772
773
774void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
775{
776 unsigned long flags, flags1;
777
778 if (!mlx4_is_master(dev: dev->dev))
779 return;
780 spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
781 spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
782 if (!dev->sriov.is_going_down) {
783 /* If there is pending one should cancel then run, otherwise
784 * won't run till previous one is ended as same work
785 * struct is used.
786 */
787 cancel_delayed_work(dwork: &dev->sriov.alias_guid.ports_guid[port].
788 alias_guid_work);
789 queue_delayed_work(wq: dev->sriov.alias_guid.ports_guid[port].wq,
790 dwork: &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, delay: 0);
791 }
792 spin_unlock_irqrestore(lock: &dev->sriov.alias_guid.ag_work_lock, flags: flags1);
793 spin_unlock_irqrestore(lock: &dev->sriov.going_down_lock, flags);
794}
795
796void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
797{
798 int i;
799 struct mlx4_ib_sriov *sriov = &dev->sriov;
800 struct mlx4_alias_guid_work_context *cb_ctx;
801 struct mlx4_sriov_alias_guid_port_rec_det *det;
802 struct ib_sa_query *sa_query;
803 unsigned long flags;
804
805 for (i = 0 ; i < dev->num_ports; i++) {
806 det = &sriov->alias_guid.ports_guid[i];
807 cancel_delayed_work_sync(dwork: &det->alias_guid_work);
808 spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
809 while (!list_empty(head: &det->cb_list)) {
810 cb_ctx = list_entry(det->cb_list.next,
811 struct mlx4_alias_guid_work_context,
812 list);
813 sa_query = cb_ctx->sa_query;
814 cb_ctx->sa_query = NULL;
815 list_del(entry: &cb_ctx->list);
816 spin_unlock_irqrestore(lock: &sriov->alias_guid.ag_work_lock, flags);
817 ib_sa_cancel_query(id: cb_ctx->query_id, query: sa_query);
818 wait_for_completion(&cb_ctx->done);
819 kfree(objp: cb_ctx);
820 spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
821 }
822 spin_unlock_irqrestore(lock: &sriov->alias_guid.ag_work_lock, flags);
823 }
824 for (i = 0 ; i < dev->num_ports; i++)
825 destroy_workqueue(wq: dev->sriov.alias_guid.ports_guid[i].wq);
826 ib_sa_unregister_client(client: dev->sriov.alias_guid.sa_client);
827 kfree(objp: dev->sriov.alias_guid.sa_client);
828}
829
830int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
831{
832 char alias_wq_name[15];
833 int ret = 0;
834 int i, j;
835 union ib_gid gid;
836
837 if (!mlx4_is_master(dev: dev->dev))
838 return 0;
839 dev->sriov.alias_guid.sa_client =
840 kzalloc(size: sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
841 if (!dev->sriov.alias_guid.sa_client)
842 return -ENOMEM;
843
844 ib_sa_register_client(client: dev->sriov.alias_guid.sa_client);
845
846 spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
847
848 for (i = 1; i <= dev->num_ports; ++i) {
849 if (dev->ib_dev.ops.query_gid(&dev->ib_dev, i, 0, &gid)) {
850 ret = -EFAULT;
851 goto err_unregister;
852 }
853 }
854
855 for (i = 0 ; i < dev->num_ports; i++) {
856 memset(&dev->sriov.alias_guid.ports_guid[i], 0,
857 sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
858 dev->sriov.alias_guid.ports_guid[i].state_flags |=
859 GUID_STATE_NEED_PORT_INIT;
860 for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
861 /* mark each val as it was deleted */
862 memset(dev->sriov.alias_guid.ports_guid[i].
863 all_rec_per_port[j].all_recs, 0xFF,
864 sizeof(dev->sriov.alias_guid.ports_guid[i].
865 all_rec_per_port[j].all_recs));
866 }
867 INIT_LIST_HEAD(list: &dev->sriov.alias_guid.ports_guid[i].cb_list);
868 /*prepare the records, set them to be allocated by sm*/
869 if (mlx4_ib_sm_guid_assign)
870 for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
871 mlx4_set_admin_guid(dev: dev->dev, guid: 0, entry: j, port: i + 1);
872 for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
873 invalidate_guid_record(dev, port: i + 1, index: j);
874
875 dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
876 dev->sriov.alias_guid.ports_guid[i].port = i;
877
878 snprintf(buf: alias_wq_name, size: sizeof alias_wq_name, fmt: "alias_guid%d", i);
879 dev->sriov.alias_guid.ports_guid[i].wq =
880 alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
881 if (!dev->sriov.alias_guid.ports_guid[i].wq) {
882 ret = -ENOMEM;
883 goto err_thread;
884 }
885 INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
886 alias_guid_work);
887 }
888 return 0;
889
890err_thread:
891 for (--i; i >= 0; i--) {
892 destroy_workqueue(wq: dev->sriov.alias_guid.ports_guid[i].wq);
893 dev->sriov.alias_guid.ports_guid[i].wq = NULL;
894 }
895
896err_unregister:
897 ib_sa_unregister_client(client: dev->sriov.alias_guid.sa_client);
898 kfree(objp: dev->sriov.alias_guid.sa_client);
899 dev->sriov.alias_guid.sa_client = NULL;
900 pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
901 return ret;
902}
903

source code of linux/drivers/infiniband/hw/mlx4/alias_GUID.c