IB/mlx4: Request alias GUID on demand
authorYishai Hadas <yishaih@mellanox.com>
Tue, 3 Mar 2015 15:28:49 +0000 (17:28 +0200)
committerDoug Ledford <dledford@redhat.com>
Wed, 15 Apr 2015 19:51:50 +0000 (15:51 -0400)
Request GIDs from the SM on demand, i.e., when a VF actually needs them,
and release them when the GIDs are no longer in use.

In cloud environments, this is useful for GID migrations, in which a
GID is assigned to a VF on the destination HCA, while the VF on the
source HCA is shutdown (but the GID was not administratively released).

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h

index 5b4080740321a28d301c4e8824d38c7975f7134f..0f00204d2ecea0e19f0a9917431e4bb8cbbdfa49 100644 (file)
@@ -123,6 +123,57 @@ ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
        return IB_SA_COMP_MASK(4 + index);
 }
 
+void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
+                                   int port,  int slave_init)
+{
+       __be64 curr_guid, required_guid;
+       int record_num = slave / 8;
+       int index = slave % 8;
+       int port_index = port - 1;
+       unsigned long flags;
+       int do_work = 0;
+
+       spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
+       if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
+           GUID_STATE_NEED_PORT_INIT)
+               goto unlock;
+       if (!slave_init) {
+               curr_guid = *(__be64 *)&dev->sriov.
+                       alias_guid.ports_guid[port_index].
+                       all_rec_per_port[record_num].
+                       all_recs[GUID_REC_SIZE * index];
+               if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
+                   !curr_guid)
+                       goto unlock;
+               required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
+       } else {
+               required_guid = mlx4_get_admin_guid(dev->dev, slave, port);
+               if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
+                       goto unlock;
+       }
+       *(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].
+               all_recs[GUID_REC_SIZE * index] = required_guid;
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].guid_indexes
+               |= mlx4_ib_get_aguid_comp_mask_from_ix(index);
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].status
+               = MLX4_GUID_INFO_STATUS_IDLE;
+       /* set to run immediately */
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].time_to_run = 0;
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].
+               guids_retry_schedule[index] = 0;
+       do_work = 1;
+unlock:
+       spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
+
+       if (do_work)
+               mlx4_ib_init_alias_guid_work(dev, port_index);
+}
+
 /*
  * Whenever new GUID is set/unset (guid table change) create event and
  * notify the relevant slave (master also should be notified).
index 976bea794b5f7726cd642cb08de4073abd5dcb58..e92dc9aa075e643e2693fe37048faa04698bb389 100644 (file)
@@ -2791,9 +2791,31 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
        case MLX4_DEV_EVENT_SLAVE_INIT:
                /* here, p is the slave id */
                do_slave_init(ibdev, p, 1);
+               if (mlx4_is_master(dev)) {
+                       int i;
+
+                       for (i = 1; i <= ibdev->num_ports; i++) {
+                               if (rdma_port_get_link_layer(&ibdev->ib_dev, i)
+                                       == IB_LINK_LAYER_INFINIBAND)
+                                       mlx4_ib_slave_alias_guid_event(ibdev,
+                                                                      p, i,
+                                                                      1);
+                       }
+               }
                return;
 
        case MLX4_DEV_EVENT_SLAVE_SHUTDOWN:
+               if (mlx4_is_master(dev)) {
+                       int i;
+
+                       for (i = 1; i <= ibdev->num_ports; i++) {
+                               if (rdma_port_get_link_layer(&ibdev->ib_dev, i)
+                                       == IB_LINK_LAYER_INFINIBAND)
+                                       mlx4_ib_slave_alias_guid_event(ibdev,
+                                                                      p, i,
+                                                                      0);
+                       }
+               }
                /* here, p is the slave id */
                do_slave_init(ibdev, p, 0);
                return;
index 532a8772b63fd5ec460419175a06246b564f8551..fce3934372a161680e4e4f2dd9716963e1178790 100644 (file)
@@ -798,6 +798,8 @@ int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
 void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
                             struct attribute *attr);
 ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index);
+void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
+                                   int port, int slave_init);
 
 int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *device) ;