xref: /linux/drivers/infiniband/hw/mlx4/alias_GUID.c (revision c1e7e466120b80ce49e91af0c9da1ce6dee4844a)
1a0c64a17SJack Morgenstein /*
2a0c64a17SJack Morgenstein  * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
3a0c64a17SJack Morgenstein  *
4a0c64a17SJack Morgenstein  * This software is available to you under a choice of one of two
5a0c64a17SJack Morgenstein  * licenses.  You may choose to be licensed under the terms of the GNU
6a0c64a17SJack Morgenstein  * General Public License (GPL) Version 2, available from the file
7a0c64a17SJack Morgenstein  * COPYING in the main directory of this source tree, or the
8a0c64a17SJack Morgenstein  * OpenIB.org BSD license below:
9a0c64a17SJack Morgenstein  *
10a0c64a17SJack Morgenstein  *     Redistribution and use in source and binary forms, with or
11a0c64a17SJack Morgenstein  *     without modification, are permitted provided that the following
12a0c64a17SJack Morgenstein  *     conditions are met:
13a0c64a17SJack Morgenstein  *
14a0c64a17SJack Morgenstein  *      - Redistributions of source code must retain the above
15a0c64a17SJack Morgenstein  *        copyright notice, this list of conditions and the following
16a0c64a17SJack Morgenstein  *        disclaimer.
17a0c64a17SJack Morgenstein  *
18a0c64a17SJack Morgenstein  *      - Redistributions in binary form must reproduce the above
19a0c64a17SJack Morgenstein  *        copyright notice, this list of conditions and the following
20a0c64a17SJack Morgenstein  *        disclaimer in the documentation and/or other materials
21a0c64a17SJack Morgenstein  *        provided with the distribution.
22a0c64a17SJack Morgenstein  *
23a0c64a17SJack Morgenstein  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24a0c64a17SJack Morgenstein  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25a0c64a17SJack Morgenstein  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26a0c64a17SJack Morgenstein  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27a0c64a17SJack Morgenstein  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28a0c64a17SJack Morgenstein  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29a0c64a17SJack Morgenstein  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30a0c64a17SJack Morgenstein  * SOFTWARE.
31a0c64a17SJack Morgenstein  */
32a0c64a17SJack Morgenstein  /***********************************************************/
33a0c64a17SJack Morgenstein /*This file support the handling of the Alias GUID feature. */
34a0c64a17SJack Morgenstein /***********************************************************/
35a0c64a17SJack Morgenstein #include <rdma/ib_mad.h>
36a0c64a17SJack Morgenstein #include <rdma/ib_smi.h>
37a0c64a17SJack Morgenstein #include <rdma/ib_cache.h>
38a0c64a17SJack Morgenstein #include <rdma/ib_sa.h>
39a0c64a17SJack Morgenstein #include <rdma/ib_pack.h>
40a0c64a17SJack Morgenstein #include <linux/mlx4/cmd.h>
41a0c64a17SJack Morgenstein #include <linux/module.h>
42a0c64a17SJack Morgenstein #include <linux/init.h>
43a0c64a17SJack Morgenstein #include <linux/errno.h>
44a0c64a17SJack Morgenstein #include <rdma/ib_user_verbs.h>
45a0c64a17SJack Morgenstein #include <linux/delay.h>
46a0c64a17SJack Morgenstein #include "mlx4_ib.h"
47a0c64a17SJack Morgenstein 
48a0c64a17SJack Morgenstein /*
49a0c64a17SJack Morgenstein The driver keeps the current state of all guids, as they are in the HW.
50a0c64a17SJack Morgenstein Whenever we receive an smp mad GUIDInfo record, the data will be cached.
51a0c64a17SJack Morgenstein */
52a0c64a17SJack Morgenstein 
53a0c64a17SJack Morgenstein struct mlx4_alias_guid_work_context {
54a0c64a17SJack Morgenstein 	u8 port;
55a0c64a17SJack Morgenstein 	struct mlx4_ib_dev     *dev ;
56a0c64a17SJack Morgenstein 	struct ib_sa_query     *sa_query;
57a0c64a17SJack Morgenstein 	struct completion	done;
58a0c64a17SJack Morgenstein 	int			query_id;
59a0c64a17SJack Morgenstein 	struct list_head	list;
60a0c64a17SJack Morgenstein 	int			block_num;
61a0c64a17SJack Morgenstein };
62a0c64a17SJack Morgenstein 
63a0c64a17SJack Morgenstein struct mlx4_next_alias_guid_work {
64a0c64a17SJack Morgenstein 	u8 port;
65a0c64a17SJack Morgenstein 	u8 block_num;
66a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid_info_rec_det rec_det;
67a0c64a17SJack Morgenstein };
68a0c64a17SJack Morgenstein 
69a0c64a17SJack Morgenstein 
70a0c64a17SJack Morgenstein void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
71a0c64a17SJack Morgenstein 					 u8 port_num, u8 *p_data)
72a0c64a17SJack Morgenstein {
73a0c64a17SJack Morgenstein 	int i;
74a0c64a17SJack Morgenstein 	u64 guid_indexes;
75a0c64a17SJack Morgenstein 	int slave_id;
76a0c64a17SJack Morgenstein 	int port_index = port_num - 1;
77a0c64a17SJack Morgenstein 
78a0c64a17SJack Morgenstein 	if (!mlx4_is_master(dev->dev))
79a0c64a17SJack Morgenstein 		return;
80a0c64a17SJack Morgenstein 
81a0c64a17SJack Morgenstein 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
82a0c64a17SJack Morgenstein 				   ports_guid[port_num - 1].
83a0c64a17SJack Morgenstein 				   all_rec_per_port[block_num].guid_indexes);
84a0c64a17SJack Morgenstein 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
85a0c64a17SJack Morgenstein 
86a0c64a17SJack Morgenstein 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
87a0c64a17SJack Morgenstein 		/* The location of the specific index starts from bit number 4
88a0c64a17SJack Morgenstein 		 * until bit num 11 */
89a0c64a17SJack Morgenstein 		if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
90a0c64a17SJack Morgenstein 			slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
91a0c64a17SJack Morgenstein 			if (slave_id >= dev->dev->num_slaves) {
92a0c64a17SJack Morgenstein 				pr_debug("The last slave: %d\n", slave_id);
93a0c64a17SJack Morgenstein 				return;
94a0c64a17SJack Morgenstein 			}
95a0c64a17SJack Morgenstein 
96a0c64a17SJack Morgenstein 			/* cache the guid: */
97a0c64a17SJack Morgenstein 			memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
98a0c64a17SJack Morgenstein 			       &p_data[i * GUID_REC_SIZE],
99a0c64a17SJack Morgenstein 			       GUID_REC_SIZE);
100a0c64a17SJack Morgenstein 		} else
101a0c64a17SJack Morgenstein 			pr_debug("Guid number: %d in block: %d"
102a0c64a17SJack Morgenstein 				 " was not updated\n", i, block_num);
103a0c64a17SJack Morgenstein 	}
104a0c64a17SJack Morgenstein }
105a0c64a17SJack Morgenstein 
106a0c64a17SJack Morgenstein static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
107a0c64a17SJack Morgenstein {
108a0c64a17SJack Morgenstein 	if (index >= NUM_ALIAS_GUID_PER_PORT) {
109a0c64a17SJack Morgenstein 		pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
110a0c64a17SJack Morgenstein 		return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
111a0c64a17SJack Morgenstein 	}
112a0c64a17SJack Morgenstein 	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
113a0c64a17SJack Morgenstein }
114a0c64a17SJack Morgenstein 
115a0c64a17SJack Morgenstein 
116*c1e7e466SJack Morgenstein ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
117a0c64a17SJack Morgenstein {
118a0c64a17SJack Morgenstein 	return IB_SA_COMP_MASK(4 + index);
119a0c64a17SJack Morgenstein }
120a0c64a17SJack Morgenstein 
121a0c64a17SJack Morgenstein /*
122a0c64a17SJack Morgenstein  * Whenever new GUID is set/unset (guid table change) create event and
123a0c64a17SJack Morgenstein  * notify the relevant slave (master also should be notified).
124a0c64a17SJack Morgenstein  * If the GUID value is not as we have in the cache the slave will not be
125a0c64a17SJack Morgenstein  * updated; in this case it waits for the smp_snoop or the port management
126a0c64a17SJack Morgenstein  * event to call the function and to update the slave.
127a0c64a17SJack Morgenstein  * block_number - the index of the block (16 blocks available)
128a0c64a17SJack Morgenstein  * port_number - 1 or 2
129a0c64a17SJack Morgenstein  */
130a0c64a17SJack Morgenstein void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
131a0c64a17SJack Morgenstein 					  int block_num, u8 port_num,
132a0c64a17SJack Morgenstein 					  u8 *p_data)
133a0c64a17SJack Morgenstein {
134a0c64a17SJack Morgenstein 	int i;
135a0c64a17SJack Morgenstein 	u64 guid_indexes;
136a0c64a17SJack Morgenstein 	int slave_id;
137a0c64a17SJack Morgenstein 	enum slave_port_state new_state;
138a0c64a17SJack Morgenstein 	enum slave_port_state prev_state;
139a0c64a17SJack Morgenstein 	__be64 tmp_cur_ag, form_cache_ag;
140a0c64a17SJack Morgenstein 	enum slave_port_gen_event gen_event;
141a0c64a17SJack Morgenstein 
142a0c64a17SJack Morgenstein 	if (!mlx4_is_master(dev->dev))
143a0c64a17SJack Morgenstein 		return;
144a0c64a17SJack Morgenstein 
145a0c64a17SJack Morgenstein 	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
146a0c64a17SJack Morgenstein 				   ports_guid[port_num - 1].
147a0c64a17SJack Morgenstein 				   all_rec_per_port[block_num].guid_indexes);
148a0c64a17SJack Morgenstein 	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
149a0c64a17SJack Morgenstein 
150a0c64a17SJack Morgenstein 	/*calculate the slaves and notify them*/
151a0c64a17SJack Morgenstein 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
152a0c64a17SJack Morgenstein 		/* the location of the specific index runs from bits 4..11 */
153a0c64a17SJack Morgenstein 		if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
154a0c64a17SJack Morgenstein 			continue;
155a0c64a17SJack Morgenstein 
156a0c64a17SJack Morgenstein 		slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
157a0c64a17SJack Morgenstein 		if (slave_id >= dev->dev->num_slaves)
158a0c64a17SJack Morgenstein 			return;
159a0c64a17SJack Morgenstein 		tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
160a0c64a17SJack Morgenstein 		form_cache_ag = get_cached_alias_guid(dev, port_num,
161a0c64a17SJack Morgenstein 					(NUM_ALIAS_GUID_IN_REC * block_num) + i);
162a0c64a17SJack Morgenstein 		/*
163a0c64a17SJack Morgenstein 		 * Check if guid is not the same as in the cache,
164a0c64a17SJack Morgenstein 		 * If it is different, wait for the snoop_smp or the port mgmt
165a0c64a17SJack Morgenstein 		 * change event to update the slave on its port state change
166a0c64a17SJack Morgenstein 		 */
167a0c64a17SJack Morgenstein 		if (tmp_cur_ag != form_cache_ag)
168a0c64a17SJack Morgenstein 			continue;
169a0c64a17SJack Morgenstein 		mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
170a0c64a17SJack Morgenstein 
171a0c64a17SJack Morgenstein 		/*2 cases: Valid GUID, and Invalid Guid*/
172a0c64a17SJack Morgenstein 
173a0c64a17SJack Morgenstein 		if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
174a0c64a17SJack Morgenstein 			prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
175a0c64a17SJack Morgenstein 			new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
176a0c64a17SJack Morgenstein 								  MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
177a0c64a17SJack Morgenstein 								  &gen_event);
178a0c64a17SJack Morgenstein 			pr_debug("slave: %d, port: %d prev_port_state: %d,"
179a0c64a17SJack Morgenstein 				 " new_port_state: %d, gen_event: %d\n",
180a0c64a17SJack Morgenstein 				 slave_id, port_num, prev_state, new_state, gen_event);
181a0c64a17SJack Morgenstein 			if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
182a0c64a17SJack Morgenstein 				pr_debug("sending PORT_UP event to slave: %d, port: %d\n",
183a0c64a17SJack Morgenstein 					 slave_id, port_num);
184a0c64a17SJack Morgenstein 				mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
185a0c64a17SJack Morgenstein 							       port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
186a0c64a17SJack Morgenstein 			}
187a0c64a17SJack Morgenstein 		} else { /* request to invalidate GUID */
188a0c64a17SJack Morgenstein 			set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
189a0c64a17SJack Morgenstein 						      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
190a0c64a17SJack Morgenstein 						      &gen_event);
191a0c64a17SJack Morgenstein 			pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
192a0c64a17SJack Morgenstein 				 slave_id, port_num);
193a0c64a17SJack Morgenstein 			mlx4_gen_port_state_change_eqe(dev->dev, slave_id, port_num,
194a0c64a17SJack Morgenstein 						       MLX4_PORT_CHANGE_SUBTYPE_DOWN);
195a0c64a17SJack Morgenstein 		}
196a0c64a17SJack Morgenstein 	}
197a0c64a17SJack Morgenstein }
198a0c64a17SJack Morgenstein 
199a0c64a17SJack Morgenstein static void aliasguid_query_handler(int status,
200a0c64a17SJack Morgenstein 				    struct ib_sa_guidinfo_rec *guid_rec,
201a0c64a17SJack Morgenstein 				    void *context)
202a0c64a17SJack Morgenstein {
203a0c64a17SJack Morgenstein 	struct mlx4_ib_dev *dev;
204a0c64a17SJack Morgenstein 	struct mlx4_alias_guid_work_context *cb_ctx = context;
205a0c64a17SJack Morgenstein 	u8 port_index ;
206a0c64a17SJack Morgenstein 	int i;
207a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid_info_rec_det *rec;
208a0c64a17SJack Morgenstein 	unsigned long flags, flags1;
209a0c64a17SJack Morgenstein 
210a0c64a17SJack Morgenstein 	if (!context)
211a0c64a17SJack Morgenstein 		return;
212a0c64a17SJack Morgenstein 
213a0c64a17SJack Morgenstein 	dev = cb_ctx->dev;
214a0c64a17SJack Morgenstein 	port_index = cb_ctx->port - 1;
215a0c64a17SJack Morgenstein 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
216a0c64a17SJack Morgenstein 		all_rec_per_port[cb_ctx->block_num];
217a0c64a17SJack Morgenstein 
218a0c64a17SJack Morgenstein 	if (status) {
219a0c64a17SJack Morgenstein 		rec->status = MLX4_GUID_INFO_STATUS_IDLE;
220a0c64a17SJack Morgenstein 		pr_debug("(port: %d) failed: status = %d\n",
221a0c64a17SJack Morgenstein 			 cb_ctx->port, status);
222a0c64a17SJack Morgenstein 		goto out;
223a0c64a17SJack Morgenstein 	}
224a0c64a17SJack Morgenstein 
225a0c64a17SJack Morgenstein 	if (guid_rec->block_num != cb_ctx->block_num) {
226a0c64a17SJack Morgenstein 		pr_err("block num mismatch: %d != %d\n",
227a0c64a17SJack Morgenstein 		       cb_ctx->block_num, guid_rec->block_num);
228a0c64a17SJack Morgenstein 		goto out;
229a0c64a17SJack Morgenstein 	}
230a0c64a17SJack Morgenstein 
231a0c64a17SJack Morgenstein 	pr_debug("lid/port: %d/%d, block_num: %d\n",
232a0c64a17SJack Morgenstein 		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
233a0c64a17SJack Morgenstein 		 guid_rec->block_num);
234a0c64a17SJack Morgenstein 
235a0c64a17SJack Morgenstein 	rec = &dev->sriov.alias_guid.ports_guid[port_index].
236a0c64a17SJack Morgenstein 		all_rec_per_port[guid_rec->block_num];
237a0c64a17SJack Morgenstein 
238a0c64a17SJack Morgenstein 	rec->status = MLX4_GUID_INFO_STATUS_SET;
239a0c64a17SJack Morgenstein 	rec->method = MLX4_GUID_INFO_RECORD_SET;
240a0c64a17SJack Morgenstein 
241a0c64a17SJack Morgenstein 	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
242a0c64a17SJack Morgenstein 		__be64 tmp_cur_ag;
243a0c64a17SJack Morgenstein 		tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
244a0c64a17SJack Morgenstein 		/* check if the SM didn't assign one of the records.
245a0c64a17SJack Morgenstein 		 * if it didn't, if it was not sysadmin request:
246a0c64a17SJack Morgenstein 		 * ask the SM to give a new GUID, (instead of the driver request).
247a0c64a17SJack Morgenstein 		 */
248a0c64a17SJack Morgenstein 		if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
249a0c64a17SJack Morgenstein 			mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
250a0c64a17SJack Morgenstein 				     "block_num: %d was declined by SM, "
251a0c64a17SJack Morgenstein 				     "ownership by %d (0 = driver, 1=sysAdmin,"
252a0c64a17SJack Morgenstein 				     " 2=None)\n", __func__, i,
253a0c64a17SJack Morgenstein 				     guid_rec->block_num, rec->ownership);
254a0c64a17SJack Morgenstein 			if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
255a0c64a17SJack Morgenstein 				/* if it is driver assign, asks for new GUID from SM*/
256a0c64a17SJack Morgenstein 				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
257a0c64a17SJack Morgenstein 					MLX4_NOT_SET_GUID;
258a0c64a17SJack Morgenstein 
259a0c64a17SJack Morgenstein 				/* Mark the record as not assigned, and let it
260a0c64a17SJack Morgenstein 				 * be sent again in the next work sched.*/
261a0c64a17SJack Morgenstein 				rec->status = MLX4_GUID_INFO_STATUS_IDLE;
262*c1e7e466SJack Morgenstein 				rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
263a0c64a17SJack Morgenstein 			}
264a0c64a17SJack Morgenstein 		} else {
265a0c64a17SJack Morgenstein 		       /* properly assigned record. */
266a0c64a17SJack Morgenstein 		       /* We save the GUID we just got from the SM in the
267a0c64a17SJack Morgenstein 			* admin_guid in order to be persistent, and in the
268a0c64a17SJack Morgenstein 			* request from the sm the process will ask for the same GUID */
269a0c64a17SJack Morgenstein 			if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
270a0c64a17SJack Morgenstein 			    tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
271a0c64a17SJack Morgenstein 				/* the sysadmin assignment failed.*/
272a0c64a17SJack Morgenstein 				mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
273a0c64a17SJack Morgenstein 					     " admin guid after SysAdmin "
274a0c64a17SJack Morgenstein 					     "configuration. "
275a0c64a17SJack Morgenstein 					     "Record num %d in block_num:%d "
276a0c64a17SJack Morgenstein 					     "was declined by SM, "
277a0c64a17SJack Morgenstein 					     "new val(0x%llx) was kept\n",
278a0c64a17SJack Morgenstein 					      __func__, i,
279a0c64a17SJack Morgenstein 					     guid_rec->block_num,
280a0c64a17SJack Morgenstein 					     be64_to_cpu(*(__be64 *) &
281a0c64a17SJack Morgenstein 							 rec->all_recs[i * GUID_REC_SIZE]));
282a0c64a17SJack Morgenstein 			} else {
283a0c64a17SJack Morgenstein 				memcpy(&rec->all_recs[i * GUID_REC_SIZE],
284a0c64a17SJack Morgenstein 				       &guid_rec->guid_info_list[i * GUID_REC_SIZE],
285a0c64a17SJack Morgenstein 				       GUID_REC_SIZE);
286a0c64a17SJack Morgenstein 			}
287a0c64a17SJack Morgenstein 		}
288a0c64a17SJack Morgenstein 	}
289a0c64a17SJack Morgenstein 	/*
290a0c64a17SJack Morgenstein 	The func is call here to close the cases when the
291a0c64a17SJack Morgenstein 	sm doesn't send smp, so in the sa response the driver
292a0c64a17SJack Morgenstein 	notifies the slave.
293a0c64a17SJack Morgenstein 	*/
294a0c64a17SJack Morgenstein 	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
295a0c64a17SJack Morgenstein 					     cb_ctx->port,
296a0c64a17SJack Morgenstein 					     guid_rec->guid_info_list);
297a0c64a17SJack Morgenstein out:
298a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
299a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
300a0c64a17SJack Morgenstein 	if (!dev->sriov.is_going_down)
301a0c64a17SJack Morgenstein 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
302a0c64a17SJack Morgenstein 				   &dev->sriov.alias_guid.ports_guid[port_index].
303a0c64a17SJack Morgenstein 				   alias_guid_work, 0);
304a0c64a17SJack Morgenstein 	if (cb_ctx->sa_query) {
305a0c64a17SJack Morgenstein 		list_del(&cb_ctx->list);
306a0c64a17SJack Morgenstein 		kfree(cb_ctx);
307a0c64a17SJack Morgenstein 	} else
308a0c64a17SJack Morgenstein 		complete(&cb_ctx->done);
309a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
310a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
311a0c64a17SJack Morgenstein }
312a0c64a17SJack Morgenstein 
313a0c64a17SJack Morgenstein static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
314a0c64a17SJack Morgenstein {
315a0c64a17SJack Morgenstein 	int i;
316a0c64a17SJack Morgenstein 	u64 cur_admin_val;
317a0c64a17SJack Morgenstein 	ib_sa_comp_mask comp_mask = 0;
318a0c64a17SJack Morgenstein 
319a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
320a0c64a17SJack Morgenstein 		= MLX4_GUID_INFO_STATUS_IDLE;
321a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method
322a0c64a17SJack Morgenstein 		= MLX4_GUID_INFO_RECORD_SET;
323a0c64a17SJack Morgenstein 
324a0c64a17SJack Morgenstein 	/* calculate the comp_mask for that record.*/
325a0c64a17SJack Morgenstein 	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
326a0c64a17SJack Morgenstein 		cur_admin_val =
327a0c64a17SJack Morgenstein 			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
328a0c64a17SJack Morgenstein 			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
329a0c64a17SJack Morgenstein 		/*
330a0c64a17SJack Morgenstein 		check the admin value: if it's for delete (~00LL) or
331a0c64a17SJack Morgenstein 		it is the first guid of the first record (hw guid) or
332a0c64a17SJack Morgenstein 		the records is not in ownership of the sysadmin and the sm doesn't
333a0c64a17SJack Morgenstein 		need to assign GUIDs, then don't put it up for assignment.
334a0c64a17SJack Morgenstein 		*/
335a0c64a17SJack Morgenstein 		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
336a0c64a17SJack Morgenstein 		    (!index && !i) ||
337a0c64a17SJack Morgenstein 		    MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
338a0c64a17SJack Morgenstein 		    ports_guid[port - 1].all_rec_per_port[index].ownership)
339a0c64a17SJack Morgenstein 			continue;
340*c1e7e466SJack Morgenstein 		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
341a0c64a17SJack Morgenstein 	}
342a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.ports_guid[port - 1].
343a0c64a17SJack Morgenstein 		all_rec_per_port[index].guid_indexes = comp_mask;
344a0c64a17SJack Morgenstein }
345a0c64a17SJack Morgenstein 
346a0c64a17SJack Morgenstein static int set_guid_rec(struct ib_device *ibdev,
347a0c64a17SJack Morgenstein 			u8 port, int index,
348a0c64a17SJack Morgenstein 			struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
349a0c64a17SJack Morgenstein {
350a0c64a17SJack Morgenstein 	int err;
351a0c64a17SJack Morgenstein 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
352a0c64a17SJack Morgenstein 	struct ib_sa_guidinfo_rec guid_info_rec;
353a0c64a17SJack Morgenstein 	ib_sa_comp_mask comp_mask;
354a0c64a17SJack Morgenstein 	struct ib_port_attr attr;
355a0c64a17SJack Morgenstein 	struct mlx4_alias_guid_work_context *callback_context;
356a0c64a17SJack Morgenstein 	unsigned long resched_delay, flags, flags1;
357a0c64a17SJack Morgenstein 	struct list_head *head =
358a0c64a17SJack Morgenstein 		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
359a0c64a17SJack Morgenstein 
360a0c64a17SJack Morgenstein 	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
361a0c64a17SJack Morgenstein 	if (err) {
362a0c64a17SJack Morgenstein 		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
363a0c64a17SJack Morgenstein 			 err, port);
364a0c64a17SJack Morgenstein 		return err;
365a0c64a17SJack Morgenstein 	}
366a0c64a17SJack Morgenstein 	/*check the port was configured by the sm, otherwise no need to send */
367a0c64a17SJack Morgenstein 	if (attr.state != IB_PORT_ACTIVE) {
368a0c64a17SJack Morgenstein 		pr_debug("port %d not active...rescheduling\n", port);
369a0c64a17SJack Morgenstein 		resched_delay = 5 * HZ;
370a0c64a17SJack Morgenstein 		err = -EAGAIN;
371a0c64a17SJack Morgenstein 		goto new_schedule;
372a0c64a17SJack Morgenstein 	}
373a0c64a17SJack Morgenstein 
374a0c64a17SJack Morgenstein 	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
375a0c64a17SJack Morgenstein 	if (!callback_context) {
376a0c64a17SJack Morgenstein 		err = -ENOMEM;
377a0c64a17SJack Morgenstein 		resched_delay = HZ * 5;
378a0c64a17SJack Morgenstein 		goto new_schedule;
379a0c64a17SJack Morgenstein 	}
380a0c64a17SJack Morgenstein 	callback_context->port = port;
381a0c64a17SJack Morgenstein 	callback_context->dev = dev;
382a0c64a17SJack Morgenstein 	callback_context->block_num = index;
383a0c64a17SJack Morgenstein 
384a0c64a17SJack Morgenstein 	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
385a0c64a17SJack Morgenstein 
386a0c64a17SJack Morgenstein 	guid_info_rec.lid = cpu_to_be16(attr.lid);
387a0c64a17SJack Morgenstein 	guid_info_rec.block_num = index;
388a0c64a17SJack Morgenstein 
389a0c64a17SJack Morgenstein 	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
390a0c64a17SJack Morgenstein 	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
391a0c64a17SJack Morgenstein 	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
392a0c64a17SJack Morgenstein 		rec_det->guid_indexes;
393a0c64a17SJack Morgenstein 
394a0c64a17SJack Morgenstein 	init_completion(&callback_context->done);
395a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
396a0c64a17SJack Morgenstein 	list_add_tail(&callback_context->list, head);
397a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
398a0c64a17SJack Morgenstein 
399a0c64a17SJack Morgenstein 	callback_context->query_id =
400a0c64a17SJack Morgenstein 		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
401a0c64a17SJack Morgenstein 					  ibdev, port, &guid_info_rec,
402a0c64a17SJack Morgenstein 					  comp_mask, rec_det->method, 1000,
403a0c64a17SJack Morgenstein 					  GFP_KERNEL, aliasguid_query_handler,
404a0c64a17SJack Morgenstein 					  callback_context,
405a0c64a17SJack Morgenstein 					  &callback_context->sa_query);
406a0c64a17SJack Morgenstein 	if (callback_context->query_id < 0) {
407a0c64a17SJack Morgenstein 		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
408a0c64a17SJack Morgenstein 			 "%d. will reschedule to the next 1 sec.\n",
409a0c64a17SJack Morgenstein 			 callback_context->query_id);
410a0c64a17SJack Morgenstein 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
411a0c64a17SJack Morgenstein 		list_del(&callback_context->list);
412a0c64a17SJack Morgenstein 		kfree(callback_context);
413a0c64a17SJack Morgenstein 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
414a0c64a17SJack Morgenstein 		resched_delay = 1 * HZ;
415a0c64a17SJack Morgenstein 		err = -EAGAIN;
416a0c64a17SJack Morgenstein 		goto new_schedule;
417a0c64a17SJack Morgenstein 	}
418a0c64a17SJack Morgenstein 	err = 0;
419a0c64a17SJack Morgenstein 	goto out;
420a0c64a17SJack Morgenstein 
421a0c64a17SJack Morgenstein new_schedule:
422a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
423a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
424a0c64a17SJack Morgenstein 	invalidate_guid_record(dev, port, index);
425a0c64a17SJack Morgenstein 	if (!dev->sriov.is_going_down) {
426a0c64a17SJack Morgenstein 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
427a0c64a17SJack Morgenstein 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
428a0c64a17SJack Morgenstein 				   resched_delay);
429a0c64a17SJack Morgenstein 	}
430a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
431a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
432a0c64a17SJack Morgenstein 
433a0c64a17SJack Morgenstein out:
434a0c64a17SJack Morgenstein 	return err;
435a0c64a17SJack Morgenstein }
436a0c64a17SJack Morgenstein 
437a0c64a17SJack Morgenstein void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
438a0c64a17SJack Morgenstein {
439a0c64a17SJack Morgenstein 	int i;
440a0c64a17SJack Morgenstein 	unsigned long flags, flags1;
441a0c64a17SJack Morgenstein 
442a0c64a17SJack Morgenstein 	pr_debug("port %d\n", port);
443a0c64a17SJack Morgenstein 
444a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
445a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
446a0c64a17SJack Morgenstein 	for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
447a0c64a17SJack Morgenstein 		invalidate_guid_record(dev, port, i);
448a0c64a17SJack Morgenstein 
449a0c64a17SJack Morgenstein 	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
450a0c64a17SJack Morgenstein 		/*
451a0c64a17SJack Morgenstein 		make sure no work waits in the queue, if the work is already
452a0c64a17SJack Morgenstein 		queued(not on the timer) the cancel will fail. That is not a problem
453a0c64a17SJack Morgenstein 		because we just want the work started.
454a0c64a17SJack Morgenstein 		*/
455a0c64a17SJack Morgenstein 		__cancel_delayed_work(&dev->sriov.alias_guid.
456a0c64a17SJack Morgenstein 				      ports_guid[port - 1].alias_guid_work);
457a0c64a17SJack Morgenstein 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
458a0c64a17SJack Morgenstein 				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
459a0c64a17SJack Morgenstein 				   0);
460a0c64a17SJack Morgenstein 	}
461a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
462a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
463a0c64a17SJack Morgenstein }
464a0c64a17SJack Morgenstein 
465a0c64a17SJack Morgenstein /* The function returns the next record that was
466a0c64a17SJack Morgenstein  * not configured (or failed to be configured) */
467a0c64a17SJack Morgenstein static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
468a0c64a17SJack Morgenstein 				     struct mlx4_next_alias_guid_work *rec)
469a0c64a17SJack Morgenstein {
470a0c64a17SJack Morgenstein 	int j;
471a0c64a17SJack Morgenstein 	unsigned long flags;
472a0c64a17SJack Morgenstein 
473a0c64a17SJack Morgenstein 	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
474a0c64a17SJack Morgenstein 		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
475a0c64a17SJack Morgenstein 		if (dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status ==
476a0c64a17SJack Morgenstein 		    MLX4_GUID_INFO_STATUS_IDLE) {
477a0c64a17SJack Morgenstein 			memcpy(&rec->rec_det,
478a0c64a17SJack Morgenstein 			       &dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j],
479a0c64a17SJack Morgenstein 			       sizeof (struct mlx4_sriov_alias_guid_info_rec_det));
480a0c64a17SJack Morgenstein 			rec->port = port;
481a0c64a17SJack Morgenstein 			rec->block_num = j;
482a0c64a17SJack Morgenstein 			dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status =
483a0c64a17SJack Morgenstein 				MLX4_GUID_INFO_STATUS_PENDING;
484a0c64a17SJack Morgenstein 			spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
485a0c64a17SJack Morgenstein 			return 0;
486a0c64a17SJack Morgenstein 		}
487a0c64a17SJack Morgenstein 		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
488a0c64a17SJack Morgenstein 	}
489a0c64a17SJack Morgenstein 	return -ENOENT;
490a0c64a17SJack Morgenstein }
491a0c64a17SJack Morgenstein 
492a0c64a17SJack Morgenstein static void set_administratively_guid_record(struct mlx4_ib_dev *dev, int port,
493a0c64a17SJack Morgenstein 					     int rec_index,
494a0c64a17SJack Morgenstein 					     struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
495a0c64a17SJack Morgenstein {
496a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].guid_indexes =
497a0c64a17SJack Morgenstein 		rec_det->guid_indexes;
498a0c64a17SJack Morgenstein 	memcpy(dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].all_recs,
499a0c64a17SJack Morgenstein 	       rec_det->all_recs, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
500a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].status =
501a0c64a17SJack Morgenstein 		rec_det->status;
502a0c64a17SJack Morgenstein }
503a0c64a17SJack Morgenstein 
504a0c64a17SJack Morgenstein static void set_all_slaves_guids(struct mlx4_ib_dev *dev, int port)
505a0c64a17SJack Morgenstein {
506a0c64a17SJack Morgenstein 	int j;
507a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid_info_rec_det rec_det ;
508a0c64a17SJack Morgenstein 
509a0c64a17SJack Morgenstein 	for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT ; j++) {
510a0c64a17SJack Morgenstein 		memset(rec_det.all_recs, 0, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
511a0c64a17SJack Morgenstein 		rec_det.guid_indexes = (!j ? 0 : IB_SA_GUIDINFO_REC_GID0) |
512a0c64a17SJack Morgenstein 			IB_SA_GUIDINFO_REC_GID1 | IB_SA_GUIDINFO_REC_GID2 |
513a0c64a17SJack Morgenstein 			IB_SA_GUIDINFO_REC_GID3 | IB_SA_GUIDINFO_REC_GID4 |
514a0c64a17SJack Morgenstein 			IB_SA_GUIDINFO_REC_GID5 | IB_SA_GUIDINFO_REC_GID6 |
515a0c64a17SJack Morgenstein 			IB_SA_GUIDINFO_REC_GID7;
516a0c64a17SJack Morgenstein 		rec_det.status = MLX4_GUID_INFO_STATUS_IDLE;
517a0c64a17SJack Morgenstein 		set_administratively_guid_record(dev, port, j, &rec_det);
518a0c64a17SJack Morgenstein 	}
519a0c64a17SJack Morgenstein }
520a0c64a17SJack Morgenstein 
521a0c64a17SJack Morgenstein static void alias_guid_work(struct work_struct *work)
522a0c64a17SJack Morgenstein {
523a0c64a17SJack Morgenstein 	struct delayed_work *delay = to_delayed_work(work);
524a0c64a17SJack Morgenstein 	int ret = 0;
525a0c64a17SJack Morgenstein 	struct mlx4_next_alias_guid_work *rec;
526a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
527a0c64a17SJack Morgenstein 		container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
528a0c64a17SJack Morgenstein 			     alias_guid_work);
529a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
530a0c64a17SJack Morgenstein 	struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
531a0c64a17SJack Morgenstein 						struct mlx4_ib_sriov,
532a0c64a17SJack Morgenstein 						alias_guid);
533a0c64a17SJack Morgenstein 	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
534a0c64a17SJack Morgenstein 
535a0c64a17SJack Morgenstein 	rec = kzalloc(sizeof *rec, GFP_KERNEL);
536a0c64a17SJack Morgenstein 	if (!rec) {
537a0c64a17SJack Morgenstein 		pr_err("alias_guid_work: No Memory\n");
538a0c64a17SJack Morgenstein 		return;
539a0c64a17SJack Morgenstein 	}
540a0c64a17SJack Morgenstein 
541a0c64a17SJack Morgenstein 	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
542a0c64a17SJack Morgenstein 	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
543a0c64a17SJack Morgenstein 	if (ret) {
544a0c64a17SJack Morgenstein 		pr_debug("No more records to update.\n");
545a0c64a17SJack Morgenstein 		goto out;
546a0c64a17SJack Morgenstein 	}
547a0c64a17SJack Morgenstein 
548a0c64a17SJack Morgenstein 	set_guid_rec(&dev->ib_dev, rec->port + 1, rec->block_num,
549a0c64a17SJack Morgenstein 		     &rec->rec_det);
550a0c64a17SJack Morgenstein 
551a0c64a17SJack Morgenstein out:
552a0c64a17SJack Morgenstein 	kfree(rec);
553a0c64a17SJack Morgenstein }
554a0c64a17SJack Morgenstein 
555a0c64a17SJack Morgenstein 
556a0c64a17SJack Morgenstein void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
557a0c64a17SJack Morgenstein {
558a0c64a17SJack Morgenstein 	unsigned long flags, flags1;
559a0c64a17SJack Morgenstein 
560a0c64a17SJack Morgenstein 	if (!mlx4_is_master(dev->dev))
561a0c64a17SJack Morgenstein 		return;
562a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
563a0c64a17SJack Morgenstein 	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
564a0c64a17SJack Morgenstein 	if (!dev->sriov.is_going_down) {
565a0c64a17SJack Morgenstein 		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
566a0c64a17SJack Morgenstein 			   &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
567a0c64a17SJack Morgenstein 	}
568a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
569a0c64a17SJack Morgenstein 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
570a0c64a17SJack Morgenstein }
571a0c64a17SJack Morgenstein 
572a0c64a17SJack Morgenstein void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
573a0c64a17SJack Morgenstein {
574a0c64a17SJack Morgenstein 	int i;
575a0c64a17SJack Morgenstein 	struct mlx4_ib_sriov *sriov = &dev->sriov;
576a0c64a17SJack Morgenstein 	struct mlx4_alias_guid_work_context *cb_ctx;
577a0c64a17SJack Morgenstein 	struct mlx4_sriov_alias_guid_port_rec_det *det;
578a0c64a17SJack Morgenstein 	struct ib_sa_query *sa_query;
579a0c64a17SJack Morgenstein 	unsigned long flags;
580a0c64a17SJack Morgenstein 
581a0c64a17SJack Morgenstein 	for (i = 0 ; i < dev->num_ports; i++) {
582a0c64a17SJack Morgenstein 		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
583a0c64a17SJack Morgenstein 		det = &sriov->alias_guid.ports_guid[i];
584a0c64a17SJack Morgenstein 		spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
585a0c64a17SJack Morgenstein 		while (!list_empty(&det->cb_list)) {
586a0c64a17SJack Morgenstein 			cb_ctx = list_entry(det->cb_list.next,
587a0c64a17SJack Morgenstein 					    struct mlx4_alias_guid_work_context,
588a0c64a17SJack Morgenstein 					    list);
589a0c64a17SJack Morgenstein 			sa_query = cb_ctx->sa_query;
590a0c64a17SJack Morgenstein 			cb_ctx->sa_query = NULL;
591a0c64a17SJack Morgenstein 			list_del(&cb_ctx->list);
592a0c64a17SJack Morgenstein 			spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
593a0c64a17SJack Morgenstein 			ib_sa_cancel_query(cb_ctx->query_id, sa_query);
594a0c64a17SJack Morgenstein 			wait_for_completion(&cb_ctx->done);
595a0c64a17SJack Morgenstein 			kfree(cb_ctx);
596a0c64a17SJack Morgenstein 			spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
597a0c64a17SJack Morgenstein 		}
598a0c64a17SJack Morgenstein 		spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
599a0c64a17SJack Morgenstein 	}
600a0c64a17SJack Morgenstein 	for (i = 0 ; i < dev->num_ports; i++) {
601a0c64a17SJack Morgenstein 		flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
602a0c64a17SJack Morgenstein 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
603a0c64a17SJack Morgenstein 	}
604a0c64a17SJack Morgenstein 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
605a0c64a17SJack Morgenstein 	kfree(dev->sriov.alias_guid.sa_client);
606a0c64a17SJack Morgenstein }
607a0c64a17SJack Morgenstein 
608a0c64a17SJack Morgenstein int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
609a0c64a17SJack Morgenstein {
610a0c64a17SJack Morgenstein 	char alias_wq_name[15];
611a0c64a17SJack Morgenstein 	int ret = 0;
612a0c64a17SJack Morgenstein 	int i, j, k;
613a0c64a17SJack Morgenstein 	union ib_gid gid;
614a0c64a17SJack Morgenstein 
615a0c64a17SJack Morgenstein 	if (!mlx4_is_master(dev->dev))
616a0c64a17SJack Morgenstein 		return 0;
617a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.sa_client =
618a0c64a17SJack Morgenstein 		kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
619a0c64a17SJack Morgenstein 	if (!dev->sriov.alias_guid.sa_client)
620a0c64a17SJack Morgenstein 		return -ENOMEM;
621a0c64a17SJack Morgenstein 
622a0c64a17SJack Morgenstein 	ib_sa_register_client(dev->sriov.alias_guid.sa_client);
623a0c64a17SJack Morgenstein 
624a0c64a17SJack Morgenstein 	spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
625a0c64a17SJack Morgenstein 
626a0c64a17SJack Morgenstein 	for (i = 1; i <= dev->num_ports; ++i) {
627a0c64a17SJack Morgenstein 		if (dev->ib_dev.query_gid(&dev->ib_dev , i, 0, &gid)) {
628a0c64a17SJack Morgenstein 			ret = -EFAULT;
629a0c64a17SJack Morgenstein 			goto err_unregister;
630a0c64a17SJack Morgenstein 		}
631a0c64a17SJack Morgenstein 	}
632a0c64a17SJack Morgenstein 
633a0c64a17SJack Morgenstein 	for (i = 0 ; i < dev->num_ports; i++) {
634a0c64a17SJack Morgenstein 		memset(&dev->sriov.alias_guid.ports_guid[i], 0,
635a0c64a17SJack Morgenstein 		       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
636a0c64a17SJack Morgenstein 		/*Check if the SM doesn't need to assign the GUIDs*/
637a0c64a17SJack Morgenstein 		for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
638a0c64a17SJack Morgenstein 			if (mlx4_ib_sm_guid_assign) {
639a0c64a17SJack Morgenstein 				dev->sriov.alias_guid.ports_guid[i].
640a0c64a17SJack Morgenstein 					all_rec_per_port[j].
641a0c64a17SJack Morgenstein 					ownership = MLX4_GUID_DRIVER_ASSIGN;
642a0c64a17SJack Morgenstein 				continue;
643a0c64a17SJack Morgenstein 			}
644a0c64a17SJack Morgenstein 			dev->sriov.alias_guid.ports_guid[i].all_rec_per_port[j].
645a0c64a17SJack Morgenstein 					ownership = MLX4_GUID_NONE_ASSIGN;
646a0c64a17SJack Morgenstein 			/*mark each val as it was deleted,
647a0c64a17SJack Morgenstein 			  till the sysAdmin will give it valid val*/
648a0c64a17SJack Morgenstein 			for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
649a0c64a17SJack Morgenstein 				*(__be64 *)&dev->sriov.alias_guid.ports_guid[i].
650a0c64a17SJack Morgenstein 					all_rec_per_port[j].all_recs[GUID_REC_SIZE * k] =
651a0c64a17SJack Morgenstein 						cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
652a0c64a17SJack Morgenstein 			}
653a0c64a17SJack Morgenstein 		}
654a0c64a17SJack Morgenstein 		INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
655a0c64a17SJack Morgenstein 		/*prepare the records, set them to be allocated by sm*/
656a0c64a17SJack Morgenstein 		for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
657a0c64a17SJack Morgenstein 			invalidate_guid_record(dev, i + 1, j);
658a0c64a17SJack Morgenstein 
659a0c64a17SJack Morgenstein 		dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
660a0c64a17SJack Morgenstein 		dev->sriov.alias_guid.ports_guid[i].port  = i;
661a0c64a17SJack Morgenstein 		if (mlx4_ib_sm_guid_assign)
662a0c64a17SJack Morgenstein 			set_all_slaves_guids(dev, i);
663a0c64a17SJack Morgenstein 
664a0c64a17SJack Morgenstein 		snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
665a0c64a17SJack Morgenstein 		dev->sriov.alias_guid.ports_guid[i].wq =
666a0c64a17SJack Morgenstein 			create_singlethread_workqueue(alias_wq_name);
667a0c64a17SJack Morgenstein 		if (!dev->sriov.alias_guid.ports_guid[i].wq) {
668a0c64a17SJack Morgenstein 			ret = -ENOMEM;
669a0c64a17SJack Morgenstein 			goto err_thread;
670a0c64a17SJack Morgenstein 		}
671a0c64a17SJack Morgenstein 		INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
672a0c64a17SJack Morgenstein 			  alias_guid_work);
673a0c64a17SJack Morgenstein 	}
674a0c64a17SJack Morgenstein 	return 0;
675a0c64a17SJack Morgenstein 
676a0c64a17SJack Morgenstein err_thread:
677a0c64a17SJack Morgenstein 	for (--i; i >= 0; i--) {
678a0c64a17SJack Morgenstein 		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
679a0c64a17SJack Morgenstein 		dev->sriov.alias_guid.ports_guid[i].wq = NULL;
680a0c64a17SJack Morgenstein 	}
681a0c64a17SJack Morgenstein 
682a0c64a17SJack Morgenstein err_unregister:
683a0c64a17SJack Morgenstein 	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
684a0c64a17SJack Morgenstein 	kfree(dev->sriov.alias_guid.sa_client);
685a0c64a17SJack Morgenstein 	dev->sriov.alias_guid.sa_client = NULL;
686a0c64a17SJack Morgenstein 	pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
687a0c64a17SJack Morgenstein 	return ret;
688a0c64a17SJack Morgenstein }
689