Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032  /***********************************************************/
0033 /*This file support the handling of the Alias GUID feature. */
0034 /***********************************************************/
0035 #include <rdma/ib_mad.h>
0036 #include <rdma/ib_smi.h>
0037 #include <rdma/ib_cache.h>
0038 #include <rdma/ib_sa.h>
0039 #include <rdma/ib_pack.h>
0040 #include <linux/mlx4/cmd.h>
0041 #include <linux/init.h>
0042 #include <linux/errno.h>
0043 #include <rdma/ib_user_verbs.h>
0044 #include <linux/delay.h>
0045 #include "mlx4_ib.h"
0046 
0047 /*
0048 The driver keeps the current state of all guids, as they are in the HW.
0049 Whenever we receive an smp mad GUIDInfo record, the data will be cached.
0050 */
0051 
0052 struct mlx4_alias_guid_work_context {
0053     u8 port;
0054     struct mlx4_ib_dev     *dev ;
0055     struct ib_sa_query     *sa_query;
0056     struct completion   done;
0057     int         query_id;
0058     struct list_head    list;
0059     int         block_num;
0060     ib_sa_comp_mask     guid_indexes;
0061     u8          method;
0062 };
0063 
0064 struct mlx4_next_alias_guid_work {
0065     u8 port;
0066     u8 block_num;
0067     u8 method;
0068     struct mlx4_sriov_alias_guid_info_rec_det rec_det;
0069 };
0070 
0071 static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
0072                      int *resched_delay_sec);
0073 
0074 void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
0075                      u32 port_num, u8 *p_data)
0076 {
0077     int i;
0078     u64 guid_indexes;
0079     int slave_id;
0080     u32 port_index = port_num - 1;
0081 
0082     if (!mlx4_is_master(dev->dev))
0083         return;
0084 
0085     guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
0086                    ports_guid[port_num - 1].
0087                    all_rec_per_port[block_num].guid_indexes);
0088     pr_debug("port: %u, guid_indexes: 0x%llx\n", port_num, guid_indexes);
0089 
0090     for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
0091         /* The location of the specific index starts from bit number 4
0092          * until bit num 11 */
0093         if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
0094             slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
0095             if (slave_id >= dev->dev->num_slaves) {
0096                 pr_debug("The last slave: %d\n", slave_id);
0097                 return;
0098             }
0099 
0100             /* cache the guid: */
0101             memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
0102                    &p_data[i * GUID_REC_SIZE],
0103                    GUID_REC_SIZE);
0104         } else
0105             pr_debug("Guid number: %d in block: %d"
0106                  " was not updated\n", i, block_num);
0107     }
0108 }
0109 
0110 static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
0111 {
0112     if (index >= NUM_ALIAS_GUID_PER_PORT) {
0113         pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
0114         return (__force __be64) -1;
0115     }
0116     return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
0117 }
0118 
0119 
0120 ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
0121 {
0122     return IB_SA_COMP_MASK(4 + index);
0123 }
0124 
0125 void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
0126                     int port,  int slave_init)
0127 {
0128     __be64 curr_guid, required_guid;
0129     int record_num = slave / 8;
0130     int index = slave % 8;
0131     int port_index = port - 1;
0132     unsigned long flags;
0133     int do_work = 0;
0134 
0135     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
0136     if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
0137         GUID_STATE_NEED_PORT_INIT)
0138         goto unlock;
0139     if (!slave_init) {
0140         curr_guid = *(__be64 *)&dev->sriov.
0141             alias_guid.ports_guid[port_index].
0142             all_rec_per_port[record_num].
0143             all_recs[GUID_REC_SIZE * index];
0144         if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
0145             !curr_guid)
0146             goto unlock;
0147         required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
0148     } else {
0149         required_guid = mlx4_get_admin_guid(dev->dev, slave, port);
0150         if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
0151             goto unlock;
0152     }
0153     *(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
0154         all_rec_per_port[record_num].
0155         all_recs[GUID_REC_SIZE * index] = required_guid;
0156     dev->sriov.alias_guid.ports_guid[port_index].
0157         all_rec_per_port[record_num].guid_indexes
0158         |= mlx4_ib_get_aguid_comp_mask_from_ix(index);
0159     dev->sriov.alias_guid.ports_guid[port_index].
0160         all_rec_per_port[record_num].status
0161         = MLX4_GUID_INFO_STATUS_IDLE;
0162     /* set to run immediately */
0163     dev->sriov.alias_guid.ports_guid[port_index].
0164         all_rec_per_port[record_num].time_to_run = 0;
0165     dev->sriov.alias_guid.ports_guid[port_index].
0166         all_rec_per_port[record_num].
0167         guids_retry_schedule[index] = 0;
0168     do_work = 1;
0169 unlock:
0170     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
0171 
0172     if (do_work)
0173         mlx4_ib_init_alias_guid_work(dev, port_index);
0174 }
0175 
0176 /*
0177  * Whenever new GUID is set/unset (guid table change) create event and
0178  * notify the relevant slave (master also should be notified).
0179  * If the GUID value is not as we have in the cache the slave will not be
0180  * updated; in this case it waits for the smp_snoop or the port management
0181  * event to call the function and to update the slave.
0182  * block_number - the index of the block (16 blocks available)
0183  * port_number - 1 or 2
0184  */
0185 void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
0186                       int block_num, u32 port_num,
0187                       u8 *p_data)
0188 {
0189     int i;
0190     u64 guid_indexes;
0191     int slave_id, slave_port;
0192     enum slave_port_state new_state;
0193     enum slave_port_state prev_state;
0194     __be64 tmp_cur_ag, form_cache_ag;
0195     enum slave_port_gen_event gen_event;
0196     struct mlx4_sriov_alias_guid_info_rec_det *rec;
0197     unsigned long flags;
0198     __be64 required_value;
0199 
0200     if (!mlx4_is_master(dev->dev))
0201         return;
0202 
0203     rec = &dev->sriov.alias_guid.ports_guid[port_num - 1].
0204             all_rec_per_port[block_num];
0205     guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
0206                    ports_guid[port_num - 1].
0207                    all_rec_per_port[block_num].guid_indexes);
0208     pr_debug("port: %u, guid_indexes: 0x%llx\n", port_num, guid_indexes);
0209 
0210     /*calculate the slaves and notify them*/
0211     for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
0212         /* the location of the specific index runs from bits 4..11 */
0213         if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
0214             continue;
0215 
0216         slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
0217         if (slave_id >= dev->dev->persist->num_vfs + 1)
0218             return;
0219 
0220         slave_port = mlx4_phys_to_slave_port(dev->dev, slave_id, port_num);
0221         if (slave_port < 0) /* this port isn't available for the VF */
0222             continue;
0223 
0224         tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
0225         form_cache_ag = get_cached_alias_guid(dev, port_num,
0226                     (NUM_ALIAS_GUID_IN_REC * block_num) + i);
0227         /*
0228          * Check if guid is not the same as in the cache,
0229          * If it is different, wait for the snoop_smp or the port mgmt
0230          * change event to update the slave on its port state change
0231          */
0232         if (tmp_cur_ag != form_cache_ag)
0233             continue;
0234 
0235         spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
0236         required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
0237 
0238         if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
0239             required_value = 0;
0240 
0241         if (tmp_cur_ag == required_value) {
0242             rec->guid_indexes = rec->guid_indexes &
0243                    ~mlx4_ib_get_aguid_comp_mask_from_ix(i);
0244         } else {
0245             /* may notify port down if value is 0 */
0246             if (tmp_cur_ag != MLX4_NOT_SET_GUID) {
0247                 spin_unlock_irqrestore(&dev->sriov.
0248                     alias_guid.ag_work_lock, flags);
0249                 continue;
0250             }
0251         }
0252         spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock,
0253                        flags);
0254         mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
0255         /*2 cases: Valid GUID, and Invalid Guid*/
0256 
0257         if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
0258             prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
0259             new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
0260                                   MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
0261                                   &gen_event);
0262             pr_debug("slave: %d, port: %u prev_port_state: %d,"
0263                  " new_port_state: %d, gen_event: %d\n",
0264                  slave_id, port_num, prev_state, new_state, gen_event);
0265             if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
0266                 pr_debug("sending PORT_UP event to slave: %d, port: %u\n",
0267                      slave_id, port_num);
0268                 mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
0269                                    port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
0270             }
0271         } else { /* request to invalidate GUID */
0272             set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
0273                               MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
0274                               &gen_event);
0275             if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) {
0276                 pr_debug("sending PORT DOWN event to slave: %d, port: %u\n",
0277                      slave_id, port_num);
0278                 mlx4_gen_port_state_change_eqe(dev->dev,
0279                                    slave_id,
0280                                    port_num,
0281                                    MLX4_PORT_CHANGE_SUBTYPE_DOWN);
0282             }
0283         }
0284     }
0285 }
0286 
0287 static void aliasguid_query_handler(int status,
0288                     struct ib_sa_guidinfo_rec *guid_rec,
0289                     void *context)
0290 {
0291     struct mlx4_ib_dev *dev;
0292     struct mlx4_alias_guid_work_context *cb_ctx = context;
0293     u8 port_index ;
0294     int i;
0295     struct mlx4_sriov_alias_guid_info_rec_det *rec;
0296     unsigned long flags, flags1;
0297     ib_sa_comp_mask declined_guid_indexes = 0;
0298     ib_sa_comp_mask applied_guid_indexes = 0;
0299     unsigned int resched_delay_sec = 0;
0300 
0301     if (!context)
0302         return;
0303 
0304     dev = cb_ctx->dev;
0305     port_index = cb_ctx->port - 1;
0306     rec = &dev->sriov.alias_guid.ports_guid[port_index].
0307         all_rec_per_port[cb_ctx->block_num];
0308 
0309     if (status) {
0310         pr_debug("(port: %d) failed: status = %d\n",
0311              cb_ctx->port, status);
0312         rec->time_to_run = ktime_get_boottime_ns() + 1 * NSEC_PER_SEC;
0313         goto out;
0314     }
0315 
0316     if (guid_rec->block_num != cb_ctx->block_num) {
0317         pr_err("block num mismatch: %d != %d\n",
0318                cb_ctx->block_num, guid_rec->block_num);
0319         goto out;
0320     }
0321 
0322     pr_debug("lid/port: %d/%d, block_num: %d\n",
0323          be16_to_cpu(guid_rec->lid), cb_ctx->port,
0324          guid_rec->block_num);
0325 
0326     rec = &dev->sriov.alias_guid.ports_guid[port_index].
0327         all_rec_per_port[guid_rec->block_num];
0328 
0329     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
0330     for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
0331         __be64 sm_response, required_val;
0332 
0333         if (!(cb_ctx->guid_indexes &
0334             mlx4_ib_get_aguid_comp_mask_from_ix(i)))
0335             continue;
0336         sm_response = *(__be64 *)&guid_rec->guid_info_list
0337                 [i * GUID_REC_SIZE];
0338         required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
0339         if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) {
0340             if (required_val ==
0341                 cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
0342                 goto next_entry;
0343 
0344             /* A new value was set till we got the response */
0345             pr_debug("need to set new value %llx, record num %d, block_num:%d\n",
0346                  be64_to_cpu(required_val),
0347                  i, guid_rec->block_num);
0348             goto entry_declined;
0349         }
0350 
0351         /* check if the SM didn't assign one of the records.
0352          * if it didn't, re-ask for.
0353          */
0354         if (sm_response == MLX4_NOT_SET_GUID) {
0355             if (rec->guids_retry_schedule[i] == 0)
0356                 mlx4_ib_warn(&dev->ib_dev,
0357                          "%s:Record num %d in  block_num: %d was declined by SM\n",
0358                          __func__, i,
0359                          guid_rec->block_num);
0360             goto entry_declined;
0361         } else {
0362                /* properly assigned record. */
0363                /* We save the GUID we just got from the SM in the
0364             * admin_guid in order to be persistent, and in the
0365             * request from the sm the process will ask for the same GUID */
0366             if (required_val &&
0367                 sm_response != required_val) {
0368                 /* Warn only on first retry */
0369                 if (rec->guids_retry_schedule[i] == 0)
0370                     mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
0371                              " admin guid after SysAdmin "
0372                              "configuration. "
0373                              "Record num %d in block_num:%d "
0374                              "was declined by SM, "
0375                              "new val(0x%llx) was kept, SM returned (0x%llx)\n",
0376                               __func__, i,
0377                              guid_rec->block_num,
0378                              be64_to_cpu(required_val),
0379                              be64_to_cpu(sm_response));
0380                 goto entry_declined;
0381             } else {
0382                 *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
0383                     sm_response;
0384                 if (required_val == 0)
0385                     mlx4_set_admin_guid(dev->dev,
0386                                 sm_response,
0387                                 (guid_rec->block_num
0388                                 * NUM_ALIAS_GUID_IN_REC) + i,
0389                                 cb_ctx->port);
0390                 goto next_entry;
0391             }
0392         }
0393 entry_declined:
0394         declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
0395         rec->guids_retry_schedule[i] =
0396             (rec->guids_retry_schedule[i] == 0) ?  1 :
0397             min((unsigned int)60,
0398                 rec->guids_retry_schedule[i] * 2);
0399         /* using the minimum value among all entries in that record */
0400         resched_delay_sec = (resched_delay_sec == 0) ?
0401                 rec->guids_retry_schedule[i] :
0402                 min(resched_delay_sec,
0403                     rec->guids_retry_schedule[i]);
0404         continue;
0405 
0406 next_entry:
0407         rec->guids_retry_schedule[i] = 0;
0408     }
0409 
0410     applied_guid_indexes =  cb_ctx->guid_indexes & ~declined_guid_indexes;
0411     if (declined_guid_indexes ||
0412         rec->guid_indexes & ~(applied_guid_indexes)) {
0413         pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n",
0414              guid_rec->block_num,
0415              be64_to_cpu((__force __be64)rec->guid_indexes),
0416              be64_to_cpu((__force __be64)applied_guid_indexes),
0417              be64_to_cpu((__force __be64)declined_guid_indexes));
0418         rec->time_to_run = ktime_get_boottime_ns() +
0419             resched_delay_sec * NSEC_PER_SEC;
0420     } else {
0421         rec->status = MLX4_GUID_INFO_STATUS_SET;
0422     }
0423     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
0424     /*
0425     The func is call here to close the cases when the
0426     sm doesn't send smp, so in the sa response the driver
0427     notifies the slave.
0428     */
0429     mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
0430                          cb_ctx->port,
0431                          guid_rec->guid_info_list);
0432 out:
0433     spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
0434     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0435     if (!dev->sriov.is_going_down) {
0436         get_low_record_time_index(dev, port_index, &resched_delay_sec);
0437         queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
0438                    &dev->sriov.alias_guid.ports_guid[port_index].
0439                    alias_guid_work,
0440                    msecs_to_jiffies(resched_delay_sec * 1000));
0441     }
0442     if (cb_ctx->sa_query) {
0443         list_del(&cb_ctx->list);
0444         kfree(cb_ctx);
0445     } else
0446         complete(&cb_ctx->done);
0447     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0448     spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
0449 }
0450 
0451 static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
0452 {
0453     int i;
0454     u64 cur_admin_val;
0455     ib_sa_comp_mask comp_mask = 0;
0456 
0457     dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
0458         = MLX4_GUID_INFO_STATUS_SET;
0459 
0460     /* calculate the comp_mask for that record.*/
0461     for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
0462         cur_admin_val =
0463             *(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
0464             all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
0465         /*
0466         check the admin value: if it's for delete (~00LL) or
0467         it is the first guid of the first record (hw guid) or
0468         the records is not in ownership of the sysadmin and the sm doesn't
0469         need to assign GUIDs, then don't put it up for assignment.
0470         */
0471         if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
0472             (!index && !i))
0473             continue;
0474         comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
0475     }
0476     dev->sriov.alias_guid.ports_guid[port - 1].
0477         all_rec_per_port[index].guid_indexes |= comp_mask;
0478     if (dev->sriov.alias_guid.ports_guid[port - 1].
0479         all_rec_per_port[index].guid_indexes)
0480         dev->sriov.alias_guid.ports_guid[port - 1].
0481         all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE;
0482 
0483 }
0484 
0485 static int set_guid_rec(struct ib_device *ibdev,
0486             struct mlx4_next_alias_guid_work *rec)
0487 {
0488     int err;
0489     struct mlx4_ib_dev *dev = to_mdev(ibdev);
0490     struct ib_sa_guidinfo_rec guid_info_rec;
0491     ib_sa_comp_mask comp_mask;
0492     struct ib_port_attr attr;
0493     struct mlx4_alias_guid_work_context *callback_context;
0494     unsigned long resched_delay, flags, flags1;
0495     u8 port = rec->port + 1;
0496     int index = rec->block_num;
0497     struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det;
0498     struct list_head *head =
0499         &dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
0500 
0501     memset(&attr, 0, sizeof(attr));
0502     err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
0503     if (err) {
0504         pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
0505              err, port);
0506         return err;
0507     }
0508     /*check the port was configured by the sm, otherwise no need to send */
0509     if (attr.state != IB_PORT_ACTIVE) {
0510         pr_debug("port %d not active...rescheduling\n", port);
0511         resched_delay = 5 * HZ;
0512         err = -EAGAIN;
0513         goto new_schedule;
0514     }
0515 
0516     callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
0517     if (!callback_context) {
0518         err = -ENOMEM;
0519         resched_delay = HZ * 5;
0520         goto new_schedule;
0521     }
0522     callback_context->port = port;
0523     callback_context->dev = dev;
0524     callback_context->block_num = index;
0525     callback_context->guid_indexes = rec_det->guid_indexes;
0526     callback_context->method = rec->method;
0527 
0528     memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
0529 
0530     guid_info_rec.lid = ib_lid_be16(attr.lid);
0531     guid_info_rec.block_num = index;
0532 
0533     memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
0534            GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
0535     comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
0536         rec_det->guid_indexes;
0537 
0538     init_completion(&callback_context->done);
0539     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0540     list_add_tail(&callback_context->list, head);
0541     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0542 
0543     callback_context->query_id =
0544         ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
0545                       ibdev, port, &guid_info_rec,
0546                       comp_mask, rec->method, 1000,
0547                       GFP_KERNEL, aliasguid_query_handler,
0548                       callback_context,
0549                       &callback_context->sa_query);
0550     if (callback_context->query_id < 0) {
0551         pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
0552              "%d. will reschedule to the next 1 sec.\n",
0553              callback_context->query_id);
0554         spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0555         list_del(&callback_context->list);
0556         kfree(callback_context);
0557         spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0558         resched_delay = 1 * HZ;
0559         err = -EAGAIN;
0560         goto new_schedule;
0561     }
0562     err = 0;
0563     goto out;
0564 
0565 new_schedule:
0566     spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
0567     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0568     invalidate_guid_record(dev, port, index);
0569     if (!dev->sriov.is_going_down) {
0570         queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
0571                    &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
0572                    resched_delay);
0573     }
0574     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0575     spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
0576 
0577 out:
0578     return err;
0579 }
0580 
0581 static void mlx4_ib_guid_port_init(struct mlx4_ib_dev *dev, int port)
0582 {
0583     int j, k, entry;
0584     __be64 guid;
0585 
0586     /*Check if the SM doesn't need to assign the GUIDs*/
0587     for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
0588         for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
0589             entry = j * NUM_ALIAS_GUID_IN_REC + k;
0590             /* no request for the 0 entry (hw guid) */
0591             if (!entry || entry > dev->dev->persist->num_vfs ||
0592                 !mlx4_is_slave_active(dev->dev, entry))
0593                 continue;
0594             guid = mlx4_get_admin_guid(dev->dev, entry, port);
0595             *(__be64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
0596                 all_rec_per_port[j].all_recs
0597                 [GUID_REC_SIZE * k] = guid;
0598             pr_debug("guid was set, entry=%d, val=0x%llx, port=%d\n",
0599                  entry,
0600                  be64_to_cpu(guid),
0601                  port);
0602         }
0603     }
0604 }
0605 void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
0606 {
0607     int i;
0608     unsigned long flags, flags1;
0609 
0610     pr_debug("port %d\n", port);
0611 
0612     spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
0613     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0614 
0615     if (dev->sriov.alias_guid.ports_guid[port - 1].state_flags &
0616         GUID_STATE_NEED_PORT_INIT) {
0617         mlx4_ib_guid_port_init(dev, port);
0618         dev->sriov.alias_guid.ports_guid[port - 1].state_flags &=
0619             (~GUID_STATE_NEED_PORT_INIT);
0620     }
0621     for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
0622         invalidate_guid_record(dev, port, i);
0623 
0624     if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
0625         /*
0626         make sure no work waits in the queue, if the work is already
0627         queued(not on the timer) the cancel will fail. That is not a problem
0628         because we just want the work started.
0629         */
0630         cancel_delayed_work(&dev->sriov.alias_guid.
0631                       ports_guid[port - 1].alias_guid_work);
0632         queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
0633                    &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
0634                    0);
0635     }
0636     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0637     spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
0638 }
0639 
0640 static void set_required_record(struct mlx4_ib_dev *dev, u8 port,
0641                 struct mlx4_next_alias_guid_work *next_rec,
0642                 int record_index)
0643 {
0644     int i;
0645     int lowset_time_entry = -1;
0646     int lowest_time = 0;
0647     ib_sa_comp_mask delete_guid_indexes = 0;
0648     ib_sa_comp_mask set_guid_indexes = 0;
0649     struct mlx4_sriov_alias_guid_info_rec_det *rec =
0650             &dev->sriov.alias_guid.ports_guid[port].
0651             all_rec_per_port[record_index];
0652 
0653     for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
0654         if (!(rec->guid_indexes &
0655             mlx4_ib_get_aguid_comp_mask_from_ix(i)))
0656             continue;
0657 
0658         if (*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] ==
0659                 cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
0660             delete_guid_indexes |=
0661                 mlx4_ib_get_aguid_comp_mask_from_ix(i);
0662         else
0663             set_guid_indexes |=
0664                 mlx4_ib_get_aguid_comp_mask_from_ix(i);
0665 
0666         if (lowset_time_entry == -1 || rec->guids_retry_schedule[i] <=
0667             lowest_time) {
0668             lowset_time_entry = i;
0669             lowest_time = rec->guids_retry_schedule[i];
0670         }
0671     }
0672 
0673     memcpy(&next_rec->rec_det, rec, sizeof(*rec));
0674     next_rec->port = port;
0675     next_rec->block_num = record_index;
0676 
0677     if (*(__be64 *)&rec->all_recs[lowset_time_entry * GUID_REC_SIZE] ==
0678                 cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) {
0679         next_rec->rec_det.guid_indexes = delete_guid_indexes;
0680         next_rec->method = MLX4_GUID_INFO_RECORD_DELETE;
0681     } else {
0682         next_rec->rec_det.guid_indexes = set_guid_indexes;
0683         next_rec->method = MLX4_GUID_INFO_RECORD_SET;
0684     }
0685 }
0686 
0687 /* return index of record that should be updated based on lowest
0688  * rescheduled time
0689  */
0690 static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
0691                      int *resched_delay_sec)
0692 {
0693     int record_index = -1;
0694     u64 low_record_time = 0;
0695     struct mlx4_sriov_alias_guid_info_rec_det rec;
0696     int j;
0697 
0698     for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
0699         rec = dev->sriov.alias_guid.ports_guid[port].
0700             all_rec_per_port[j];
0701         if (rec.status == MLX4_GUID_INFO_STATUS_IDLE &&
0702             rec.guid_indexes) {
0703             if (record_index == -1 ||
0704                 rec.time_to_run < low_record_time) {
0705                 record_index = j;
0706                 low_record_time = rec.time_to_run;
0707             }
0708         }
0709     }
0710     if (resched_delay_sec) {
0711         u64 curr_time = ktime_get_boottime_ns();
0712 
0713         *resched_delay_sec = (low_record_time < curr_time) ? 0 :
0714             div_u64((low_record_time - curr_time), NSEC_PER_SEC);
0715     }
0716 
0717     return record_index;
0718 }
0719 
0720 /* The function returns the next record that was
0721  * not configured (or failed to be configured) */
0722 static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
0723                      struct mlx4_next_alias_guid_work *rec)
0724 {
0725     unsigned long flags;
0726     int record_index;
0727     int ret = 0;
0728 
0729     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
0730     record_index = get_low_record_time_index(dev, port, NULL);
0731 
0732     if (record_index < 0) {
0733         ret = -ENOENT;
0734         goto out;
0735     }
0736 
0737     set_required_record(dev, port, rec, record_index);
0738 out:
0739     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
0740     return ret;
0741 }
0742 
0743 static void alias_guid_work(struct work_struct *work)
0744 {
0745     struct delayed_work *delay = to_delayed_work(work);
0746     int ret = 0;
0747     struct mlx4_next_alias_guid_work *rec;
0748     struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
0749         container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
0750                  alias_guid_work);
0751     struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
0752     struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
0753                         struct mlx4_ib_sriov,
0754                         alias_guid);
0755     struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
0756 
0757     rec = kzalloc(sizeof *rec, GFP_KERNEL);
0758     if (!rec)
0759         return;
0760 
0761     pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
0762     ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
0763     if (ret) {
0764         pr_debug("No more records to update.\n");
0765         goto out;
0766     }
0767 
0768     set_guid_rec(&dev->ib_dev, rec);
0769 out:
0770     kfree(rec);
0771 }
0772 
0773 
0774 void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
0775 {
0776     unsigned long flags, flags1;
0777 
0778     if (!mlx4_is_master(dev->dev))
0779         return;
0780     spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
0781     spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
0782     if (!dev->sriov.is_going_down) {
0783         /* If there is pending one should cancel then run, otherwise
0784           * won't run till previous one is ended as same work
0785           * struct is used.
0786           */
0787         cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port].
0788                     alias_guid_work);
0789         queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
0790                &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
0791     }
0792     spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
0793     spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
0794 }
0795 
0796 void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
0797 {
0798     int i;
0799     struct mlx4_ib_sriov *sriov = &dev->sriov;
0800     struct mlx4_alias_guid_work_context *cb_ctx;
0801     struct mlx4_sriov_alias_guid_port_rec_det *det;
0802     struct ib_sa_query *sa_query;
0803     unsigned long flags;
0804 
0805     for (i = 0 ; i < dev->num_ports; i++) {
0806         det = &sriov->alias_guid.ports_guid[i];
0807         cancel_delayed_work_sync(&det->alias_guid_work);
0808         spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
0809         while (!list_empty(&det->cb_list)) {
0810             cb_ctx = list_entry(det->cb_list.next,
0811                         struct mlx4_alias_guid_work_context,
0812                         list);
0813             sa_query = cb_ctx->sa_query;
0814             cb_ctx->sa_query = NULL;
0815             list_del(&cb_ctx->list);
0816             spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
0817             ib_sa_cancel_query(cb_ctx->query_id, sa_query);
0818             wait_for_completion(&cb_ctx->done);
0819             kfree(cb_ctx);
0820             spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
0821         }
0822         spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
0823     }
0824     for (i = 0 ; i < dev->num_ports; i++)
0825         destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
0826     ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
0827     kfree(dev->sriov.alias_guid.sa_client);
0828 }
0829 
0830 int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
0831 {
0832     char alias_wq_name[15];
0833     int ret = 0;
0834     int i, j;
0835     union ib_gid gid;
0836 
0837     if (!mlx4_is_master(dev->dev))
0838         return 0;
0839     dev->sriov.alias_guid.sa_client =
0840         kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
0841     if (!dev->sriov.alias_guid.sa_client)
0842         return -ENOMEM;
0843 
0844     ib_sa_register_client(dev->sriov.alias_guid.sa_client);
0845 
0846     spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
0847 
0848     for (i = 1; i <= dev->num_ports; ++i) {
0849         if (dev->ib_dev.ops.query_gid(&dev->ib_dev, i, 0, &gid)) {
0850             ret = -EFAULT;
0851             goto err_unregister;
0852         }
0853     }
0854 
0855     for (i = 0 ; i < dev->num_ports; i++) {
0856         memset(&dev->sriov.alias_guid.ports_guid[i], 0,
0857                sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
0858         dev->sriov.alias_guid.ports_guid[i].state_flags |=
0859                 GUID_STATE_NEED_PORT_INIT;
0860         for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
0861             /* mark each val as it was deleted */
0862             memset(dev->sriov.alias_guid.ports_guid[i].
0863                 all_rec_per_port[j].all_recs, 0xFF,
0864                 sizeof(dev->sriov.alias_guid.ports_guid[i].
0865                 all_rec_per_port[j].all_recs));
0866         }
0867         INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
0868         /*prepare the records, set them to be allocated by sm*/
0869         if (mlx4_ib_sm_guid_assign)
0870             for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
0871                 mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
0872         for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
0873             invalidate_guid_record(dev, i + 1, j);
0874 
0875         dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
0876         dev->sriov.alias_guid.ports_guid[i].port  = i;
0877 
0878         snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
0879         dev->sriov.alias_guid.ports_guid[i].wq =
0880             alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
0881         if (!dev->sriov.alias_guid.ports_guid[i].wq) {
0882             ret = -ENOMEM;
0883             goto err_thread;
0884         }
0885         INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
0886               alias_guid_work);
0887     }
0888     return 0;
0889 
0890 err_thread:
0891     for (--i; i >= 0; i--) {
0892         destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
0893         dev->sriov.alias_guid.ports_guid[i].wq = NULL;
0894     }
0895 
0896 err_unregister:
0897     ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
0898     kfree(dev->sriov.alias_guid.sa_client);
0899     dev->sriov.alias_guid.sa_client = NULL;
0900     pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
0901     return ret;
0902 }