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