]> Git Repo - linux.git/blob - drivers/infiniband/hw/mlx4/alias_GUID.c
iptables: use match, target and data copy_to_user helpers
[linux.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                 return;
760
761         pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
762         ret = get_next_record_to_update(dev, 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(&dev->ib_dev, rec);
769 out:
770         kfree(rec);
771 }
772
773
774 void 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))
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 cancell then run, otherwise
784                   * won't run till previous one is ended as same work
785                   * struct is used.
786                   */
787                 cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port].
788                                     alias_guid_work);
789                 queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
790                            &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
791         }
792         spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
793         spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
794 }
795
796 void 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                 cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
807                 det = &sriov->alias_guid.ports_guid[i];
808                 spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
809                 while (!list_empty(&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(&cb_ctx->list);
816                         spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
817                         ib_sa_cancel_query(cb_ctx->query_id, sa_query);
818                         wait_for_completion(&cb_ctx->done);
819                         kfree(cb_ctx);
820                         spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
821                 }
822                 spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
823         }
824         for (i = 0 ; i < dev->num_ports; i++) {
825                 flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
826                 destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
827         }
828         ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
829         kfree(dev->sriov.alias_guid.sa_client);
830 }
831
832 int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
833 {
834         char alias_wq_name[15];
835         int ret = 0;
836         int i, j;
837         union ib_gid gid;
838
839         if (!mlx4_is_master(dev->dev))
840                 return 0;
841         dev->sriov.alias_guid.sa_client =
842                 kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
843         if (!dev->sriov.alias_guid.sa_client)
844                 return -ENOMEM;
845
846         ib_sa_register_client(dev->sriov.alias_guid.sa_client);
847
848         spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
849
850         for (i = 1; i <= dev->num_ports; ++i) {
851                 if (dev->ib_dev.query_gid(&dev->ib_dev , i, 0, &gid)) {
852                         ret = -EFAULT;
853                         goto err_unregister;
854                 }
855         }
856
857         for (i = 0 ; i < dev->num_ports; i++) {
858                 memset(&dev->sriov.alias_guid.ports_guid[i], 0,
859                        sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
860                 dev->sriov.alias_guid.ports_guid[i].state_flags |=
861                                 GUID_STATE_NEED_PORT_INIT;
862                 for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
863                         /* mark each val as it was deleted */
864                         memset(dev->sriov.alias_guid.ports_guid[i].
865                                 all_rec_per_port[j].all_recs, 0xFF,
866                                 sizeof(dev->sriov.alias_guid.ports_guid[i].
867                                 all_rec_per_port[j].all_recs));
868                 }
869                 INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
870                 /*prepare the records, set them to be allocated by sm*/
871                 if (mlx4_ib_sm_guid_assign)
872                         for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
873                                 mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
874                 for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
875                         invalidate_guid_record(dev, i + 1, j);
876
877                 dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
878                 dev->sriov.alias_guid.ports_guid[i].port  = i;
879
880                 snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
881                 dev->sriov.alias_guid.ports_guid[i].wq =
882                         alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
883                 if (!dev->sriov.alias_guid.ports_guid[i].wq) {
884                         ret = -ENOMEM;
885                         goto err_thread;
886                 }
887                 INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
888                           alias_guid_work);
889         }
890         return 0;
891
892 err_thread:
893         for (--i; i >= 0; i--) {
894                 destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
895                 dev->sriov.alias_guid.ports_guid[i].wq = NULL;
896         }
897
898 err_unregister:
899         ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
900         kfree(dev->sriov.alias_guid.sa_client);
901         dev->sriov.alias_guid.sa_client = NULL;
902         pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
903         return ret;
904 }
This page took 0.089095 seconds and 4 git commands to generate.