aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mlx4/sysfs.c
diff options
context:
space:
mode:
authorYishai Hadas <yishaih@mellanox.com>2015-02-03 11:32:53 -0500
committerDoug Ledford <dledford@redhat.com>2015-04-15 15:51:49 -0400
commit99ee4df6aaf542b84f68d66a02de7b68b72a87a8 (patch)
tree17200b79574018628292682035d49f246b564c30 /drivers/infiniband/hw/mlx4/sysfs.c
parentc841e12add6926d64aa608687893465330b5a03e (diff)
IB/mlx4: Alias GUID adding persistency support
If the SM rejects an alias GUID request the PF driver keeps trying to acquire the specified GUID indefinitely, utilizing an exponential backoff scheme. Retrying is managed per GUID entry. Each entry that wasn't applied holds its next retry information. Retry requests to the SM consist of records of 8 consecutive GUIDS. Each record that contains GUIDs requiring retries holds its next time-to-run based on the retry information of all its GUID entries. The record having the lowest retry time will run first when that retry time arrives. Since the method (SET or DELETE) as sent to the SM applies to all the GUIDs in the record, we must handle SET requests and DELETE requests in separate SM messages (one for SETs and the other for DELETEs). To avoid race conditions where a GUID entry request (set or delete) was modified after the SM request was sent, we save the method and the requested indices as part of the callback's context -- thus, only the requested indexes are evaluated when the response is received. When an GUID entry is approved we turn off its retry-required bit, this prevents redundant SM retries from occurring on that record. The port down event should be sent only when previously it was up. Likewise, the port up event should be sent only if previously the port was down. Synchronization was added around the flows that change entries and record state to prevent race conditions. 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>
Diffstat (limited to 'drivers/infiniband/hw/mlx4/sysfs.c')
-rw-r--r--drivers/infiniband/hw/mlx4/sysfs.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/mlx4/sysfs.c b/drivers/infiniband/hw/mlx4/sysfs.c
index d10c2b8a5dad..7423d7e4a829 100644
--- a/drivers/infiniband/hw/mlx4/sysfs.c
+++ b/drivers/infiniband/hw/mlx4/sysfs.c
@@ -80,6 +80,7 @@ static ssize_t store_admin_alias_guid(struct device *dev,
80 struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; 80 struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
81 struct mlx4_ib_dev *mdev = port->dev; 81 struct mlx4_ib_dev *mdev = port->dev;
82 u64 sysadmin_ag_val; 82 u64 sysadmin_ag_val;
83 unsigned long flags;
83 84
84 record_num = mlx4_ib_iov_dentry->entry_num / 8; 85 record_num = mlx4_ib_iov_dentry->entry_num / 8;
85 guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8; 86 guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
@@ -87,6 +88,7 @@ static ssize_t store_admin_alias_guid(struct device *dev,
87 pr_err("GUID 0 block 0 is RO\n"); 88 pr_err("GUID 0 block 0 is RO\n");
88 return count; 89 return count;
89 } 90 }
91 spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);
90 sscanf(buf, "%llx", &sysadmin_ag_val); 92 sscanf(buf, "%llx", &sysadmin_ag_val);
91 *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1]. 93 *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
92 all_rec_per_port[record_num]. 94 all_rec_per_port[record_num].
@@ -96,14 +98,8 @@ static ssize_t store_admin_alias_guid(struct device *dev,
96 /* Change the state to be pending for update */ 98 /* Change the state to be pending for update */
97 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status 99 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
98 = MLX4_GUID_INFO_STATUS_IDLE ; 100 = MLX4_GUID_INFO_STATUS_IDLE ;
99
100 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
101 = MLX4_GUID_INFO_RECORD_SET;
102
103 switch (sysadmin_ag_val) { 101 switch (sysadmin_ag_val) {
104 case MLX4_GUID_FOR_DELETE_VAL: 102 case MLX4_GUID_FOR_DELETE_VAL:
105 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
106 = MLX4_GUID_INFO_RECORD_DELETE;
107 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership 103 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
108 = MLX4_GUID_SYSADMIN_ASSIGN; 104 = MLX4_GUID_SYSADMIN_ASSIGN;
109 break; 105 break;
@@ -121,8 +117,9 @@ static ssize_t store_admin_alias_guid(struct device *dev,
121 117
122 /* set the record index */ 118 /* set the record index */
123 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes 119 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
124 = mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec); 120 |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
125 121
122 spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);
126 mlx4_ib_init_alias_guid_work(mdev, port->num - 1); 123 mlx4_ib_init_alias_guid_work(mdev, port->num - 1);
127 124
128 return count; 125 return count;