18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
58c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below:
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
118c2ecf20Sopenharmony_ci *     without modification, are permitted provided that the following
128c2ecf20Sopenharmony_ci *     conditions are met:
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *      - Redistributions of source code must retain the above
158c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
168c2ecf20Sopenharmony_ci *        disclaimer.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
198c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
208c2ecf20Sopenharmony_ci *        disclaimer in the documentation and/or other materials
218c2ecf20Sopenharmony_ci *        provided with the distribution.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
308c2ecf20Sopenharmony_ci * SOFTWARE.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci /***********************************************************/
338c2ecf20Sopenharmony_ci/*This file support the handling of the Alias GUID feature. */
348c2ecf20Sopenharmony_ci/***********************************************************/
358c2ecf20Sopenharmony_ci#include <rdma/ib_mad.h>
368c2ecf20Sopenharmony_ci#include <rdma/ib_smi.h>
378c2ecf20Sopenharmony_ci#include <rdma/ib_cache.h>
388c2ecf20Sopenharmony_ci#include <rdma/ib_sa.h>
398c2ecf20Sopenharmony_ci#include <rdma/ib_pack.h>
408c2ecf20Sopenharmony_ci#include <linux/mlx4/cmd.h>
418c2ecf20Sopenharmony_ci#include <linux/module.h>
428c2ecf20Sopenharmony_ci#include <linux/init.h>
438c2ecf20Sopenharmony_ci#include <linux/errno.h>
448c2ecf20Sopenharmony_ci#include <rdma/ib_user_verbs.h>
458c2ecf20Sopenharmony_ci#include <linux/delay.h>
468c2ecf20Sopenharmony_ci#include "mlx4_ib.h"
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/*
498c2ecf20Sopenharmony_ciThe driver keeps the current state of all guids, as they are in the HW.
508c2ecf20Sopenharmony_ciWhenever we receive an smp mad GUIDInfo record, the data will be cached.
518c2ecf20Sopenharmony_ci*/
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistruct mlx4_alias_guid_work_context {
548c2ecf20Sopenharmony_ci	u8 port;
558c2ecf20Sopenharmony_ci	struct mlx4_ib_dev     *dev ;
568c2ecf20Sopenharmony_ci	struct ib_sa_query     *sa_query;
578c2ecf20Sopenharmony_ci	struct completion	done;
588c2ecf20Sopenharmony_ci	int			query_id;
598c2ecf20Sopenharmony_ci	struct list_head	list;
608c2ecf20Sopenharmony_ci	int			block_num;
618c2ecf20Sopenharmony_ci	ib_sa_comp_mask		guid_indexes;
628c2ecf20Sopenharmony_ci	u8			method;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct mlx4_next_alias_guid_work {
668c2ecf20Sopenharmony_ci	u8 port;
678c2ecf20Sopenharmony_ci	u8 block_num;
688c2ecf20Sopenharmony_ci	u8 method;
698c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det rec_det;
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
738c2ecf20Sopenharmony_ci				     int *resched_delay_sec);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_civoid mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
768c2ecf20Sopenharmony_ci					 u8 port_num, u8 *p_data)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	int i;
798c2ecf20Sopenharmony_ci	u64 guid_indexes;
808c2ecf20Sopenharmony_ci	int slave_id;
818c2ecf20Sopenharmony_ci	int port_index = port_num - 1;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (!mlx4_is_master(dev->dev))
848c2ecf20Sopenharmony_ci		return;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
878c2ecf20Sopenharmony_ci				   ports_guid[port_num - 1].
888c2ecf20Sopenharmony_ci				   all_rec_per_port[block_num].guid_indexes);
898c2ecf20Sopenharmony_ci	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
928c2ecf20Sopenharmony_ci		/* The location of the specific index starts from bit number 4
938c2ecf20Sopenharmony_ci		 * until bit num 11 */
948c2ecf20Sopenharmony_ci		if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
958c2ecf20Sopenharmony_ci			slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
968c2ecf20Sopenharmony_ci			if (slave_id >= dev->dev->num_slaves) {
978c2ecf20Sopenharmony_ci				pr_debug("The last slave: %d\n", slave_id);
988c2ecf20Sopenharmony_ci				return;
998c2ecf20Sopenharmony_ci			}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci			/* cache the guid: */
1028c2ecf20Sopenharmony_ci			memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
1038c2ecf20Sopenharmony_ci			       &p_data[i * GUID_REC_SIZE],
1048c2ecf20Sopenharmony_ci			       GUID_REC_SIZE);
1058c2ecf20Sopenharmony_ci		} else
1068c2ecf20Sopenharmony_ci			pr_debug("Guid number: %d in block: %d"
1078c2ecf20Sopenharmony_ci				 " was not updated\n", i, block_num);
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	if (index >= NUM_ALIAS_GUID_PER_PORT) {
1148c2ecf20Sopenharmony_ci		pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
1158c2ecf20Sopenharmony_ci		return (__force __be64) -1;
1168c2ecf20Sopenharmony_ci	}
1178c2ecf20Sopenharmony_ci	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	return IB_SA_COMP_MASK(4 + index);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_civoid mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
1278c2ecf20Sopenharmony_ci				    int port,  int slave_init)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	__be64 curr_guid, required_guid;
1308c2ecf20Sopenharmony_ci	int record_num = slave / 8;
1318c2ecf20Sopenharmony_ci	int index = slave % 8;
1328c2ecf20Sopenharmony_ci	int port_index = port - 1;
1338c2ecf20Sopenharmony_ci	unsigned long flags;
1348c2ecf20Sopenharmony_ci	int do_work = 0;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
1378c2ecf20Sopenharmony_ci	if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
1388c2ecf20Sopenharmony_ci	    GUID_STATE_NEED_PORT_INIT)
1398c2ecf20Sopenharmony_ci		goto unlock;
1408c2ecf20Sopenharmony_ci	if (!slave_init) {
1418c2ecf20Sopenharmony_ci		curr_guid = *(__be64 *)&dev->sriov.
1428c2ecf20Sopenharmony_ci			alias_guid.ports_guid[port_index].
1438c2ecf20Sopenharmony_ci			all_rec_per_port[record_num].
1448c2ecf20Sopenharmony_ci			all_recs[GUID_REC_SIZE * index];
1458c2ecf20Sopenharmony_ci		if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
1468c2ecf20Sopenharmony_ci		    !curr_guid)
1478c2ecf20Sopenharmony_ci			goto unlock;
1488c2ecf20Sopenharmony_ci		required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
1498c2ecf20Sopenharmony_ci	} else {
1508c2ecf20Sopenharmony_ci		required_guid = mlx4_get_admin_guid(dev->dev, slave, port);
1518c2ecf20Sopenharmony_ci		if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
1528c2ecf20Sopenharmony_ci			goto unlock;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci	*(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
1558c2ecf20Sopenharmony_ci		all_rec_per_port[record_num].
1568c2ecf20Sopenharmony_ci		all_recs[GUID_REC_SIZE * index] = required_guid;
1578c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port_index].
1588c2ecf20Sopenharmony_ci		all_rec_per_port[record_num].guid_indexes
1598c2ecf20Sopenharmony_ci		|= mlx4_ib_get_aguid_comp_mask_from_ix(index);
1608c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port_index].
1618c2ecf20Sopenharmony_ci		all_rec_per_port[record_num].status
1628c2ecf20Sopenharmony_ci		= MLX4_GUID_INFO_STATUS_IDLE;
1638c2ecf20Sopenharmony_ci	/* set to run immediately */
1648c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port_index].
1658c2ecf20Sopenharmony_ci		all_rec_per_port[record_num].time_to_run = 0;
1668c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port_index].
1678c2ecf20Sopenharmony_ci		all_rec_per_port[record_num].
1688c2ecf20Sopenharmony_ci		guids_retry_schedule[index] = 0;
1698c2ecf20Sopenharmony_ci	do_work = 1;
1708c2ecf20Sopenharmony_ciunlock:
1718c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (do_work)
1748c2ecf20Sopenharmony_ci		mlx4_ib_init_alias_guid_work(dev, port_index);
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/*
1788c2ecf20Sopenharmony_ci * Whenever new GUID is set/unset (guid table change) create event and
1798c2ecf20Sopenharmony_ci * notify the relevant slave (master also should be notified).
1808c2ecf20Sopenharmony_ci * If the GUID value is not as we have in the cache the slave will not be
1818c2ecf20Sopenharmony_ci * updated; in this case it waits for the smp_snoop or the port management
1828c2ecf20Sopenharmony_ci * event to call the function and to update the slave.
1838c2ecf20Sopenharmony_ci * block_number - the index of the block (16 blocks available)
1848c2ecf20Sopenharmony_ci * port_number - 1 or 2
1858c2ecf20Sopenharmony_ci */
1868c2ecf20Sopenharmony_civoid mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
1878c2ecf20Sopenharmony_ci					  int block_num, u8 port_num,
1888c2ecf20Sopenharmony_ci					  u8 *p_data)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	int i;
1918c2ecf20Sopenharmony_ci	u64 guid_indexes;
1928c2ecf20Sopenharmony_ci	int slave_id, slave_port;
1938c2ecf20Sopenharmony_ci	enum slave_port_state new_state;
1948c2ecf20Sopenharmony_ci	enum slave_port_state prev_state;
1958c2ecf20Sopenharmony_ci	__be64 tmp_cur_ag, form_cache_ag;
1968c2ecf20Sopenharmony_ci	enum slave_port_gen_event gen_event;
1978c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det *rec;
1988c2ecf20Sopenharmony_ci	unsigned long flags;
1998c2ecf20Sopenharmony_ci	__be64 required_value;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	if (!mlx4_is_master(dev->dev))
2028c2ecf20Sopenharmony_ci		return;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	rec = &dev->sriov.alias_guid.ports_guid[port_num - 1].
2058c2ecf20Sopenharmony_ci			all_rec_per_port[block_num];
2068c2ecf20Sopenharmony_ci	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
2078c2ecf20Sopenharmony_ci				   ports_guid[port_num - 1].
2088c2ecf20Sopenharmony_ci				   all_rec_per_port[block_num].guid_indexes);
2098c2ecf20Sopenharmony_ci	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/*calculate the slaves and notify them*/
2128c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
2138c2ecf20Sopenharmony_ci		/* the location of the specific index runs from bits 4..11 */
2148c2ecf20Sopenharmony_ci		if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
2158c2ecf20Sopenharmony_ci			continue;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
2188c2ecf20Sopenharmony_ci		if (slave_id >= dev->dev->persist->num_vfs + 1)
2198c2ecf20Sopenharmony_ci			return;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		slave_port = mlx4_phys_to_slave_port(dev->dev, slave_id, port_num);
2228c2ecf20Sopenharmony_ci		if (slave_port < 0) /* this port isn't available for the VF */
2238c2ecf20Sopenharmony_ci			continue;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci		tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
2268c2ecf20Sopenharmony_ci		form_cache_ag = get_cached_alias_guid(dev, port_num,
2278c2ecf20Sopenharmony_ci					(NUM_ALIAS_GUID_IN_REC * block_num) + i);
2288c2ecf20Sopenharmony_ci		/*
2298c2ecf20Sopenharmony_ci		 * Check if guid is not the same as in the cache,
2308c2ecf20Sopenharmony_ci		 * If it is different, wait for the snoop_smp or the port mgmt
2318c2ecf20Sopenharmony_ci		 * change event to update the slave on its port state change
2328c2ecf20Sopenharmony_ci		 */
2338c2ecf20Sopenharmony_ci		if (tmp_cur_ag != form_cache_ag)
2348c2ecf20Sopenharmony_ci			continue;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
2378c2ecf20Sopenharmony_ci		required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci		if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
2408c2ecf20Sopenharmony_ci			required_value = 0;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci		if (tmp_cur_ag == required_value) {
2438c2ecf20Sopenharmony_ci			rec->guid_indexes = rec->guid_indexes &
2448c2ecf20Sopenharmony_ci			       ~mlx4_ib_get_aguid_comp_mask_from_ix(i);
2458c2ecf20Sopenharmony_ci		} else {
2468c2ecf20Sopenharmony_ci			/* may notify port down if value is 0 */
2478c2ecf20Sopenharmony_ci			if (tmp_cur_ag != MLX4_NOT_SET_GUID) {
2488c2ecf20Sopenharmony_ci				spin_unlock_irqrestore(&dev->sriov.
2498c2ecf20Sopenharmony_ci					alias_guid.ag_work_lock, flags);
2508c2ecf20Sopenharmony_ci				continue;
2518c2ecf20Sopenharmony_ci			}
2528c2ecf20Sopenharmony_ci		}
2538c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock,
2548c2ecf20Sopenharmony_ci				       flags);
2558c2ecf20Sopenharmony_ci		mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
2568c2ecf20Sopenharmony_ci		/*2 cases: Valid GUID, and Invalid Guid*/
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
2598c2ecf20Sopenharmony_ci			prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
2608c2ecf20Sopenharmony_ci			new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
2618c2ecf20Sopenharmony_ci								  MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
2628c2ecf20Sopenharmony_ci								  &gen_event);
2638c2ecf20Sopenharmony_ci			pr_debug("slave: %d, port: %d prev_port_state: %d,"
2648c2ecf20Sopenharmony_ci				 " new_port_state: %d, gen_event: %d\n",
2658c2ecf20Sopenharmony_ci				 slave_id, port_num, prev_state, new_state, gen_event);
2668c2ecf20Sopenharmony_ci			if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
2678c2ecf20Sopenharmony_ci				pr_debug("sending PORT_UP event to slave: %d, port: %d\n",
2688c2ecf20Sopenharmony_ci					 slave_id, port_num);
2698c2ecf20Sopenharmony_ci				mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
2708c2ecf20Sopenharmony_ci							       port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
2718c2ecf20Sopenharmony_ci			}
2728c2ecf20Sopenharmony_ci		} else { /* request to invalidate GUID */
2738c2ecf20Sopenharmony_ci			set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
2748c2ecf20Sopenharmony_ci						      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
2758c2ecf20Sopenharmony_ci						      &gen_event);
2768c2ecf20Sopenharmony_ci			if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) {
2778c2ecf20Sopenharmony_ci				pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
2788c2ecf20Sopenharmony_ci					 slave_id, port_num);
2798c2ecf20Sopenharmony_ci				mlx4_gen_port_state_change_eqe(dev->dev,
2808c2ecf20Sopenharmony_ci							       slave_id,
2818c2ecf20Sopenharmony_ci							       port_num,
2828c2ecf20Sopenharmony_ci							       MLX4_PORT_CHANGE_SUBTYPE_DOWN);
2838c2ecf20Sopenharmony_ci			}
2848c2ecf20Sopenharmony_ci		}
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic void aliasguid_query_handler(int status,
2898c2ecf20Sopenharmony_ci				    struct ib_sa_guidinfo_rec *guid_rec,
2908c2ecf20Sopenharmony_ci				    void *context)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	struct mlx4_ib_dev *dev;
2938c2ecf20Sopenharmony_ci	struct mlx4_alias_guid_work_context *cb_ctx = context;
2948c2ecf20Sopenharmony_ci	u8 port_index ;
2958c2ecf20Sopenharmony_ci	int i;
2968c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det *rec;
2978c2ecf20Sopenharmony_ci	unsigned long flags, flags1;
2988c2ecf20Sopenharmony_ci	ib_sa_comp_mask declined_guid_indexes = 0;
2998c2ecf20Sopenharmony_ci	ib_sa_comp_mask applied_guid_indexes = 0;
3008c2ecf20Sopenharmony_ci	unsigned int resched_delay_sec = 0;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (!context)
3038c2ecf20Sopenharmony_ci		return;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	dev = cb_ctx->dev;
3068c2ecf20Sopenharmony_ci	port_index = cb_ctx->port - 1;
3078c2ecf20Sopenharmony_ci	rec = &dev->sriov.alias_guid.ports_guid[port_index].
3088c2ecf20Sopenharmony_ci		all_rec_per_port[cb_ctx->block_num];
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	if (status) {
3118c2ecf20Sopenharmony_ci		pr_debug("(port: %d) failed: status = %d\n",
3128c2ecf20Sopenharmony_ci			 cb_ctx->port, status);
3138c2ecf20Sopenharmony_ci		rec->time_to_run = ktime_get_boottime_ns() + 1 * NSEC_PER_SEC;
3148c2ecf20Sopenharmony_ci		goto out;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	if (guid_rec->block_num != cb_ctx->block_num) {
3188c2ecf20Sopenharmony_ci		pr_err("block num mismatch: %d != %d\n",
3198c2ecf20Sopenharmony_ci		       cb_ctx->block_num, guid_rec->block_num);
3208c2ecf20Sopenharmony_ci		goto out;
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	pr_debug("lid/port: %d/%d, block_num: %d\n",
3248c2ecf20Sopenharmony_ci		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
3258c2ecf20Sopenharmony_ci		 guid_rec->block_num);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	rec = &dev->sriov.alias_guid.ports_guid[port_index].
3288c2ecf20Sopenharmony_ci		all_rec_per_port[guid_rec->block_num];
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
3318c2ecf20Sopenharmony_ci	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
3328c2ecf20Sopenharmony_ci		__be64 sm_response, required_val;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		if (!(cb_ctx->guid_indexes &
3358c2ecf20Sopenharmony_ci			mlx4_ib_get_aguid_comp_mask_from_ix(i)))
3368c2ecf20Sopenharmony_ci			continue;
3378c2ecf20Sopenharmony_ci		sm_response = *(__be64 *)&guid_rec->guid_info_list
3388c2ecf20Sopenharmony_ci				[i * GUID_REC_SIZE];
3398c2ecf20Sopenharmony_ci		required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
3408c2ecf20Sopenharmony_ci		if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) {
3418c2ecf20Sopenharmony_ci			if (required_val ==
3428c2ecf20Sopenharmony_ci			    cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
3438c2ecf20Sopenharmony_ci				goto next_entry;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci			/* A new value was set till we got the response */
3468c2ecf20Sopenharmony_ci			pr_debug("need to set new value %llx, record num %d, block_num:%d\n",
3478c2ecf20Sopenharmony_ci				 be64_to_cpu(required_val),
3488c2ecf20Sopenharmony_ci				 i, guid_rec->block_num);
3498c2ecf20Sopenharmony_ci			goto entry_declined;
3508c2ecf20Sopenharmony_ci		}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		/* check if the SM didn't assign one of the records.
3538c2ecf20Sopenharmony_ci		 * if it didn't, re-ask for.
3548c2ecf20Sopenharmony_ci		 */
3558c2ecf20Sopenharmony_ci		if (sm_response == MLX4_NOT_SET_GUID) {
3568c2ecf20Sopenharmony_ci			if (rec->guids_retry_schedule[i] == 0)
3578c2ecf20Sopenharmony_ci				mlx4_ib_warn(&dev->ib_dev,
3588c2ecf20Sopenharmony_ci					     "%s:Record num %d in  block_num: %d was declined by SM\n",
3598c2ecf20Sopenharmony_ci					     __func__, i,
3608c2ecf20Sopenharmony_ci					     guid_rec->block_num);
3618c2ecf20Sopenharmony_ci			goto entry_declined;
3628c2ecf20Sopenharmony_ci		} else {
3638c2ecf20Sopenharmony_ci		       /* properly assigned record. */
3648c2ecf20Sopenharmony_ci		       /* We save the GUID we just got from the SM in the
3658c2ecf20Sopenharmony_ci			* admin_guid in order to be persistent, and in the
3668c2ecf20Sopenharmony_ci			* request from the sm the process will ask for the same GUID */
3678c2ecf20Sopenharmony_ci			if (required_val &&
3688c2ecf20Sopenharmony_ci			    sm_response != required_val) {
3698c2ecf20Sopenharmony_ci				/* Warn only on first retry */
3708c2ecf20Sopenharmony_ci				if (rec->guids_retry_schedule[i] == 0)
3718c2ecf20Sopenharmony_ci					mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
3728c2ecf20Sopenharmony_ci						     " admin guid after SysAdmin "
3738c2ecf20Sopenharmony_ci						     "configuration. "
3748c2ecf20Sopenharmony_ci						     "Record num %d in block_num:%d "
3758c2ecf20Sopenharmony_ci						     "was declined by SM, "
3768c2ecf20Sopenharmony_ci						     "new val(0x%llx) was kept, SM returned (0x%llx)\n",
3778c2ecf20Sopenharmony_ci						      __func__, i,
3788c2ecf20Sopenharmony_ci						     guid_rec->block_num,
3798c2ecf20Sopenharmony_ci						     be64_to_cpu(required_val),
3808c2ecf20Sopenharmony_ci						     be64_to_cpu(sm_response));
3818c2ecf20Sopenharmony_ci				goto entry_declined;
3828c2ecf20Sopenharmony_ci			} else {
3838c2ecf20Sopenharmony_ci				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
3848c2ecf20Sopenharmony_ci					sm_response;
3858c2ecf20Sopenharmony_ci				if (required_val == 0)
3868c2ecf20Sopenharmony_ci					mlx4_set_admin_guid(dev->dev,
3878c2ecf20Sopenharmony_ci							    sm_response,
3888c2ecf20Sopenharmony_ci							    (guid_rec->block_num
3898c2ecf20Sopenharmony_ci							    * NUM_ALIAS_GUID_IN_REC) + i,
3908c2ecf20Sopenharmony_ci							    cb_ctx->port);
3918c2ecf20Sopenharmony_ci				goto next_entry;
3928c2ecf20Sopenharmony_ci			}
3938c2ecf20Sopenharmony_ci		}
3948c2ecf20Sopenharmony_cientry_declined:
3958c2ecf20Sopenharmony_ci		declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
3968c2ecf20Sopenharmony_ci		rec->guids_retry_schedule[i] =
3978c2ecf20Sopenharmony_ci			(rec->guids_retry_schedule[i] == 0) ?  1 :
3988c2ecf20Sopenharmony_ci			min((unsigned int)60,
3998c2ecf20Sopenharmony_ci			    rec->guids_retry_schedule[i] * 2);
4008c2ecf20Sopenharmony_ci		/* using the minimum value among all entries in that record */
4018c2ecf20Sopenharmony_ci		resched_delay_sec = (resched_delay_sec == 0) ?
4028c2ecf20Sopenharmony_ci				rec->guids_retry_schedule[i] :
4038c2ecf20Sopenharmony_ci				min(resched_delay_sec,
4048c2ecf20Sopenharmony_ci				    rec->guids_retry_schedule[i]);
4058c2ecf20Sopenharmony_ci		continue;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cinext_entry:
4088c2ecf20Sopenharmony_ci		rec->guids_retry_schedule[i] = 0;
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	applied_guid_indexes =  cb_ctx->guid_indexes & ~declined_guid_indexes;
4128c2ecf20Sopenharmony_ci	if (declined_guid_indexes ||
4138c2ecf20Sopenharmony_ci	    rec->guid_indexes & ~(applied_guid_indexes)) {
4148c2ecf20Sopenharmony_ci		pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n",
4158c2ecf20Sopenharmony_ci			 guid_rec->block_num,
4168c2ecf20Sopenharmony_ci			 be64_to_cpu((__force __be64)rec->guid_indexes),
4178c2ecf20Sopenharmony_ci			 be64_to_cpu((__force __be64)applied_guid_indexes),
4188c2ecf20Sopenharmony_ci			 be64_to_cpu((__force __be64)declined_guid_indexes));
4198c2ecf20Sopenharmony_ci		rec->time_to_run = ktime_get_boottime_ns() +
4208c2ecf20Sopenharmony_ci			resched_delay_sec * NSEC_PER_SEC;
4218c2ecf20Sopenharmony_ci	} else {
4228c2ecf20Sopenharmony_ci		rec->status = MLX4_GUID_INFO_STATUS_SET;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
4258c2ecf20Sopenharmony_ci	/*
4268c2ecf20Sopenharmony_ci	The func is call here to close the cases when the
4278c2ecf20Sopenharmony_ci	sm doesn't send smp, so in the sa response the driver
4288c2ecf20Sopenharmony_ci	notifies the slave.
4298c2ecf20Sopenharmony_ci	*/
4308c2ecf20Sopenharmony_ci	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
4318c2ecf20Sopenharmony_ci					     cb_ctx->port,
4328c2ecf20Sopenharmony_ci					     guid_rec->guid_info_list);
4338c2ecf20Sopenharmony_ciout:
4348c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
4358c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
4368c2ecf20Sopenharmony_ci	if (!dev->sriov.is_going_down) {
4378c2ecf20Sopenharmony_ci		get_low_record_time_index(dev, port_index, &resched_delay_sec);
4388c2ecf20Sopenharmony_ci		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
4398c2ecf20Sopenharmony_ci				   &dev->sriov.alias_guid.ports_guid[port_index].
4408c2ecf20Sopenharmony_ci				   alias_guid_work,
4418c2ecf20Sopenharmony_ci				   msecs_to_jiffies(resched_delay_sec * 1000));
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci	if (cb_ctx->sa_query) {
4448c2ecf20Sopenharmony_ci		list_del(&cb_ctx->list);
4458c2ecf20Sopenharmony_ci		kfree(cb_ctx);
4468c2ecf20Sopenharmony_ci	} else
4478c2ecf20Sopenharmony_ci		complete(&cb_ctx->done);
4488c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
4498c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	int i;
4558c2ecf20Sopenharmony_ci	u64 cur_admin_val;
4568c2ecf20Sopenharmony_ci	ib_sa_comp_mask comp_mask = 0;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
4598c2ecf20Sopenharmony_ci		= MLX4_GUID_INFO_STATUS_SET;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	/* calculate the comp_mask for that record.*/
4628c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
4638c2ecf20Sopenharmony_ci		cur_admin_val =
4648c2ecf20Sopenharmony_ci			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
4658c2ecf20Sopenharmony_ci			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
4668c2ecf20Sopenharmony_ci		/*
4678c2ecf20Sopenharmony_ci		check the admin value: if it's for delete (~00LL) or
4688c2ecf20Sopenharmony_ci		it is the first guid of the first record (hw guid) or
4698c2ecf20Sopenharmony_ci		the records is not in ownership of the sysadmin and the sm doesn't
4708c2ecf20Sopenharmony_ci		need to assign GUIDs, then don't put it up for assignment.
4718c2ecf20Sopenharmony_ci		*/
4728c2ecf20Sopenharmony_ci		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
4738c2ecf20Sopenharmony_ci		    (!index && !i))
4748c2ecf20Sopenharmony_ci			continue;
4758c2ecf20Sopenharmony_ci		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.ports_guid[port - 1].
4788c2ecf20Sopenharmony_ci		all_rec_per_port[index].guid_indexes |= comp_mask;
4798c2ecf20Sopenharmony_ci	if (dev->sriov.alias_guid.ports_guid[port - 1].
4808c2ecf20Sopenharmony_ci	    all_rec_per_port[index].guid_indexes)
4818c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[port - 1].
4828c2ecf20Sopenharmony_ci		all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic int set_guid_rec(struct ib_device *ibdev,
4878c2ecf20Sopenharmony_ci			struct mlx4_next_alias_guid_work *rec)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	int err;
4908c2ecf20Sopenharmony_ci	struct mlx4_ib_dev *dev = to_mdev(ibdev);
4918c2ecf20Sopenharmony_ci	struct ib_sa_guidinfo_rec guid_info_rec;
4928c2ecf20Sopenharmony_ci	ib_sa_comp_mask comp_mask;
4938c2ecf20Sopenharmony_ci	struct ib_port_attr attr;
4948c2ecf20Sopenharmony_ci	struct mlx4_alias_guid_work_context *callback_context;
4958c2ecf20Sopenharmony_ci	unsigned long resched_delay, flags, flags1;
4968c2ecf20Sopenharmony_ci	u8 port = rec->port + 1;
4978c2ecf20Sopenharmony_ci	int index = rec->block_num;
4988c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det;
4998c2ecf20Sopenharmony_ci	struct list_head *head =
5008c2ecf20Sopenharmony_ci		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5038c2ecf20Sopenharmony_ci	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
5048c2ecf20Sopenharmony_ci	if (err) {
5058c2ecf20Sopenharmony_ci		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
5068c2ecf20Sopenharmony_ci			 err, port);
5078c2ecf20Sopenharmony_ci		return err;
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci	/*check the port was configured by the sm, otherwise no need to send */
5108c2ecf20Sopenharmony_ci	if (attr.state != IB_PORT_ACTIVE) {
5118c2ecf20Sopenharmony_ci		pr_debug("port %d not active...rescheduling\n", port);
5128c2ecf20Sopenharmony_ci		resched_delay = 5 * HZ;
5138c2ecf20Sopenharmony_ci		err = -EAGAIN;
5148c2ecf20Sopenharmony_ci		goto new_schedule;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
5188c2ecf20Sopenharmony_ci	if (!callback_context) {
5198c2ecf20Sopenharmony_ci		err = -ENOMEM;
5208c2ecf20Sopenharmony_ci		resched_delay = HZ * 5;
5218c2ecf20Sopenharmony_ci		goto new_schedule;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci	callback_context->port = port;
5248c2ecf20Sopenharmony_ci	callback_context->dev = dev;
5258c2ecf20Sopenharmony_ci	callback_context->block_num = index;
5268c2ecf20Sopenharmony_ci	callback_context->guid_indexes = rec_det->guid_indexes;
5278c2ecf20Sopenharmony_ci	callback_context->method = rec->method;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	guid_info_rec.lid = ib_lid_be16(attr.lid);
5328c2ecf20Sopenharmony_ci	guid_info_rec.block_num = index;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
5358c2ecf20Sopenharmony_ci	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
5368c2ecf20Sopenharmony_ci	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
5378c2ecf20Sopenharmony_ci		rec_det->guid_indexes;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	init_completion(&callback_context->done);
5408c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
5418c2ecf20Sopenharmony_ci	list_add_tail(&callback_context->list, head);
5428c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	callback_context->query_id =
5458c2ecf20Sopenharmony_ci		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
5468c2ecf20Sopenharmony_ci					  ibdev, port, &guid_info_rec,
5478c2ecf20Sopenharmony_ci					  comp_mask, rec->method, 1000,
5488c2ecf20Sopenharmony_ci					  GFP_KERNEL, aliasguid_query_handler,
5498c2ecf20Sopenharmony_ci					  callback_context,
5508c2ecf20Sopenharmony_ci					  &callback_context->sa_query);
5518c2ecf20Sopenharmony_ci	if (callback_context->query_id < 0) {
5528c2ecf20Sopenharmony_ci		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
5538c2ecf20Sopenharmony_ci			 "%d. will reschedule to the next 1 sec.\n",
5548c2ecf20Sopenharmony_ci			 callback_context->query_id);
5558c2ecf20Sopenharmony_ci		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
5568c2ecf20Sopenharmony_ci		list_del(&callback_context->list);
5578c2ecf20Sopenharmony_ci		kfree(callback_context);
5588c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
5598c2ecf20Sopenharmony_ci		resched_delay = 1 * HZ;
5608c2ecf20Sopenharmony_ci		err = -EAGAIN;
5618c2ecf20Sopenharmony_ci		goto new_schedule;
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci	err = 0;
5648c2ecf20Sopenharmony_ci	goto out;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_cinew_schedule:
5678c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
5688c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
5698c2ecf20Sopenharmony_ci	invalidate_guid_record(dev, port, index);
5708c2ecf20Sopenharmony_ci	if (!dev->sriov.is_going_down) {
5718c2ecf20Sopenharmony_ci		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
5728c2ecf20Sopenharmony_ci				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
5738c2ecf20Sopenharmony_ci				   resched_delay);
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
5768c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ciout:
5798c2ecf20Sopenharmony_ci	return err;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic void mlx4_ib_guid_port_init(struct mlx4_ib_dev *dev, int port)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	int j, k, entry;
5858c2ecf20Sopenharmony_ci	__be64 guid;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	/*Check if the SM doesn't need to assign the GUIDs*/
5888c2ecf20Sopenharmony_ci	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
5898c2ecf20Sopenharmony_ci		for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
5908c2ecf20Sopenharmony_ci			entry = j * NUM_ALIAS_GUID_IN_REC + k;
5918c2ecf20Sopenharmony_ci			/* no request for the 0 entry (hw guid) */
5928c2ecf20Sopenharmony_ci			if (!entry || entry > dev->dev->persist->num_vfs ||
5938c2ecf20Sopenharmony_ci			    !mlx4_is_slave_active(dev->dev, entry))
5948c2ecf20Sopenharmony_ci				continue;
5958c2ecf20Sopenharmony_ci			guid = mlx4_get_admin_guid(dev->dev, entry, port);
5968c2ecf20Sopenharmony_ci			*(__be64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
5978c2ecf20Sopenharmony_ci				all_rec_per_port[j].all_recs
5988c2ecf20Sopenharmony_ci				[GUID_REC_SIZE * k] = guid;
5998c2ecf20Sopenharmony_ci			pr_debug("guid was set, entry=%d, val=0x%llx, port=%d\n",
6008c2ecf20Sopenharmony_ci				 entry,
6018c2ecf20Sopenharmony_ci				 be64_to_cpu(guid),
6028c2ecf20Sopenharmony_ci				 port);
6038c2ecf20Sopenharmony_ci		}
6048c2ecf20Sopenharmony_ci	}
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_civoid mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	int i;
6098c2ecf20Sopenharmony_ci	unsigned long flags, flags1;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	pr_debug("port %d\n", port);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
6148c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (dev->sriov.alias_guid.ports_guid[port - 1].state_flags &
6178c2ecf20Sopenharmony_ci		GUID_STATE_NEED_PORT_INIT) {
6188c2ecf20Sopenharmony_ci		mlx4_ib_guid_port_init(dev, port);
6198c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[port - 1].state_flags &=
6208c2ecf20Sopenharmony_ci			(~GUID_STATE_NEED_PORT_INIT);
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
6238c2ecf20Sopenharmony_ci		invalidate_guid_record(dev, port, i);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
6268c2ecf20Sopenharmony_ci		/*
6278c2ecf20Sopenharmony_ci		make sure no work waits in the queue, if the work is already
6288c2ecf20Sopenharmony_ci		queued(not on the timer) the cancel will fail. That is not a problem
6298c2ecf20Sopenharmony_ci		because we just want the work started.
6308c2ecf20Sopenharmony_ci		*/
6318c2ecf20Sopenharmony_ci		cancel_delayed_work(&dev->sriov.alias_guid.
6328c2ecf20Sopenharmony_ci				      ports_guid[port - 1].alias_guid_work);
6338c2ecf20Sopenharmony_ci		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
6348c2ecf20Sopenharmony_ci				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
6358c2ecf20Sopenharmony_ci				   0);
6368c2ecf20Sopenharmony_ci	}
6378c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
6388c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic void set_required_record(struct mlx4_ib_dev *dev, u8 port,
6428c2ecf20Sopenharmony_ci				struct mlx4_next_alias_guid_work *next_rec,
6438c2ecf20Sopenharmony_ci				int record_index)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	int i;
6468c2ecf20Sopenharmony_ci	int lowset_time_entry = -1;
6478c2ecf20Sopenharmony_ci	int lowest_time = 0;
6488c2ecf20Sopenharmony_ci	ib_sa_comp_mask delete_guid_indexes = 0;
6498c2ecf20Sopenharmony_ci	ib_sa_comp_mask set_guid_indexes = 0;
6508c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det *rec =
6518c2ecf20Sopenharmony_ci			&dev->sriov.alias_guid.ports_guid[port].
6528c2ecf20Sopenharmony_ci			all_rec_per_port[record_index];
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
6558c2ecf20Sopenharmony_ci		if (!(rec->guid_indexes &
6568c2ecf20Sopenharmony_ci			mlx4_ib_get_aguid_comp_mask_from_ix(i)))
6578c2ecf20Sopenharmony_ci			continue;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci		if (*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] ==
6608c2ecf20Sopenharmony_ci				cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
6618c2ecf20Sopenharmony_ci			delete_guid_indexes |=
6628c2ecf20Sopenharmony_ci				mlx4_ib_get_aguid_comp_mask_from_ix(i);
6638c2ecf20Sopenharmony_ci		else
6648c2ecf20Sopenharmony_ci			set_guid_indexes |=
6658c2ecf20Sopenharmony_ci				mlx4_ib_get_aguid_comp_mask_from_ix(i);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci		if (lowset_time_entry == -1 || rec->guids_retry_schedule[i] <=
6688c2ecf20Sopenharmony_ci			lowest_time) {
6698c2ecf20Sopenharmony_ci			lowset_time_entry = i;
6708c2ecf20Sopenharmony_ci			lowest_time = rec->guids_retry_schedule[i];
6718c2ecf20Sopenharmony_ci		}
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	memcpy(&next_rec->rec_det, rec, sizeof(*rec));
6758c2ecf20Sopenharmony_ci	next_rec->port = port;
6768c2ecf20Sopenharmony_ci	next_rec->block_num = record_index;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (*(__be64 *)&rec->all_recs[lowset_time_entry * GUID_REC_SIZE] ==
6798c2ecf20Sopenharmony_ci				cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) {
6808c2ecf20Sopenharmony_ci		next_rec->rec_det.guid_indexes = delete_guid_indexes;
6818c2ecf20Sopenharmony_ci		next_rec->method = MLX4_GUID_INFO_RECORD_DELETE;
6828c2ecf20Sopenharmony_ci	} else {
6838c2ecf20Sopenharmony_ci		next_rec->rec_det.guid_indexes = set_guid_indexes;
6848c2ecf20Sopenharmony_ci		next_rec->method = MLX4_GUID_INFO_RECORD_SET;
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci/* return index of record that should be updated based on lowest
6898c2ecf20Sopenharmony_ci * rescheduled time
6908c2ecf20Sopenharmony_ci */
6918c2ecf20Sopenharmony_cistatic int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
6928c2ecf20Sopenharmony_ci				     int *resched_delay_sec)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	int record_index = -1;
6958c2ecf20Sopenharmony_ci	u64 low_record_time = 0;
6968c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_info_rec_det rec;
6978c2ecf20Sopenharmony_ci	int j;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
7008c2ecf20Sopenharmony_ci		rec = dev->sriov.alias_guid.ports_guid[port].
7018c2ecf20Sopenharmony_ci			all_rec_per_port[j];
7028c2ecf20Sopenharmony_ci		if (rec.status == MLX4_GUID_INFO_STATUS_IDLE &&
7038c2ecf20Sopenharmony_ci		    rec.guid_indexes) {
7048c2ecf20Sopenharmony_ci			if (record_index == -1 ||
7058c2ecf20Sopenharmony_ci			    rec.time_to_run < low_record_time) {
7068c2ecf20Sopenharmony_ci				record_index = j;
7078c2ecf20Sopenharmony_ci				low_record_time = rec.time_to_run;
7088c2ecf20Sopenharmony_ci			}
7098c2ecf20Sopenharmony_ci		}
7108c2ecf20Sopenharmony_ci	}
7118c2ecf20Sopenharmony_ci	if (resched_delay_sec) {
7128c2ecf20Sopenharmony_ci		u64 curr_time = ktime_get_boottime_ns();
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci		*resched_delay_sec = (low_record_time < curr_time) ? 0 :
7158c2ecf20Sopenharmony_ci			div_u64((low_record_time - curr_time), NSEC_PER_SEC);
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	return record_index;
7198c2ecf20Sopenharmony_ci}
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci/* The function returns the next record that was
7228c2ecf20Sopenharmony_ci * not configured (or failed to be configured) */
7238c2ecf20Sopenharmony_cistatic int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
7248c2ecf20Sopenharmony_ci				     struct mlx4_next_alias_guid_work *rec)
7258c2ecf20Sopenharmony_ci{
7268c2ecf20Sopenharmony_ci	unsigned long flags;
7278c2ecf20Sopenharmony_ci	int record_index;
7288c2ecf20Sopenharmony_ci	int ret = 0;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
7318c2ecf20Sopenharmony_ci	record_index = get_low_record_time_index(dev, port, NULL);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	if (record_index < 0) {
7348c2ecf20Sopenharmony_ci		ret = -ENOENT;
7358c2ecf20Sopenharmony_ci		goto out;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	set_required_record(dev, port, rec, record_index);
7398c2ecf20Sopenharmony_ciout:
7408c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
7418c2ecf20Sopenharmony_ci	return ret;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic void alias_guid_work(struct work_struct *work)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	struct delayed_work *delay = to_delayed_work(work);
7478c2ecf20Sopenharmony_ci	int ret = 0;
7488c2ecf20Sopenharmony_ci	struct mlx4_next_alias_guid_work *rec;
7498c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
7508c2ecf20Sopenharmony_ci		container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
7518c2ecf20Sopenharmony_ci			     alias_guid_work);
7528c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
7538c2ecf20Sopenharmony_ci	struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
7548c2ecf20Sopenharmony_ci						struct mlx4_ib_sriov,
7558c2ecf20Sopenharmony_ci						alias_guid);
7568c2ecf20Sopenharmony_ci	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	rec = kzalloc(sizeof *rec, GFP_KERNEL);
7598c2ecf20Sopenharmony_ci	if (!rec)
7608c2ecf20Sopenharmony_ci		return;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
7638c2ecf20Sopenharmony_ci	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
7648c2ecf20Sopenharmony_ci	if (ret) {
7658c2ecf20Sopenharmony_ci		pr_debug("No more records to update.\n");
7668c2ecf20Sopenharmony_ci		goto out;
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	set_guid_rec(&dev->ib_dev, rec);
7708c2ecf20Sopenharmony_ciout:
7718c2ecf20Sopenharmony_ci	kfree(rec);
7728c2ecf20Sopenharmony_ci}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_civoid mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
7768c2ecf20Sopenharmony_ci{
7778c2ecf20Sopenharmony_ci	unsigned long flags, flags1;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	if (!mlx4_is_master(dev->dev))
7808c2ecf20Sopenharmony_ci		return;
7818c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
7828c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
7838c2ecf20Sopenharmony_ci	if (!dev->sriov.is_going_down) {
7848c2ecf20Sopenharmony_ci		/* If there is pending one should cancel then run, otherwise
7858c2ecf20Sopenharmony_ci		  * won't run till previous one is ended as same work
7868c2ecf20Sopenharmony_ci		  * struct is used.
7878c2ecf20Sopenharmony_ci		  */
7888c2ecf20Sopenharmony_ci		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port].
7898c2ecf20Sopenharmony_ci				    alias_guid_work);
7908c2ecf20Sopenharmony_ci		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
7918c2ecf20Sopenharmony_ci			   &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
7928c2ecf20Sopenharmony_ci	}
7938c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
7948c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
7958c2ecf20Sopenharmony_ci}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_civoid mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
7988c2ecf20Sopenharmony_ci{
7998c2ecf20Sopenharmony_ci	int i;
8008c2ecf20Sopenharmony_ci	struct mlx4_ib_sriov *sriov = &dev->sriov;
8018c2ecf20Sopenharmony_ci	struct mlx4_alias_guid_work_context *cb_ctx;
8028c2ecf20Sopenharmony_ci	struct mlx4_sriov_alias_guid_port_rec_det *det;
8038c2ecf20Sopenharmony_ci	struct ib_sa_query *sa_query;
8048c2ecf20Sopenharmony_ci	unsigned long flags;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	for (i = 0 ; i < dev->num_ports; i++) {
8078c2ecf20Sopenharmony_ci		det = &sriov->alias_guid.ports_guid[i];
8088c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&det->alias_guid_work);
8098c2ecf20Sopenharmony_ci		spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
8108c2ecf20Sopenharmony_ci		while (!list_empty(&det->cb_list)) {
8118c2ecf20Sopenharmony_ci			cb_ctx = list_entry(det->cb_list.next,
8128c2ecf20Sopenharmony_ci					    struct mlx4_alias_guid_work_context,
8138c2ecf20Sopenharmony_ci					    list);
8148c2ecf20Sopenharmony_ci			sa_query = cb_ctx->sa_query;
8158c2ecf20Sopenharmony_ci			cb_ctx->sa_query = NULL;
8168c2ecf20Sopenharmony_ci			list_del(&cb_ctx->list);
8178c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
8188c2ecf20Sopenharmony_ci			ib_sa_cancel_query(cb_ctx->query_id, sa_query);
8198c2ecf20Sopenharmony_ci			wait_for_completion(&cb_ctx->done);
8208c2ecf20Sopenharmony_ci			kfree(cb_ctx);
8218c2ecf20Sopenharmony_ci			spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
8228c2ecf20Sopenharmony_ci		}
8238c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci	for (i = 0 ; i < dev->num_ports; i++) {
8268c2ecf20Sopenharmony_ci		flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
8278c2ecf20Sopenharmony_ci		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
8308c2ecf20Sopenharmony_ci	kfree(dev->sriov.alias_guid.sa_client);
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ciint mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	char alias_wq_name[15];
8368c2ecf20Sopenharmony_ci	int ret = 0;
8378c2ecf20Sopenharmony_ci	int i, j;
8388c2ecf20Sopenharmony_ci	union ib_gid gid;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	if (!mlx4_is_master(dev->dev))
8418c2ecf20Sopenharmony_ci		return 0;
8428c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.sa_client =
8438c2ecf20Sopenharmony_ci		kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
8448c2ecf20Sopenharmony_ci	if (!dev->sriov.alias_guid.sa_client)
8458c2ecf20Sopenharmony_ci		return -ENOMEM;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	ib_sa_register_client(dev->sriov.alias_guid.sa_client);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	for (i = 1; i <= dev->num_ports; ++i) {
8528c2ecf20Sopenharmony_ci		if (dev->ib_dev.ops.query_gid(&dev->ib_dev, i, 0, &gid)) {
8538c2ecf20Sopenharmony_ci			ret = -EFAULT;
8548c2ecf20Sopenharmony_ci			goto err_unregister;
8558c2ecf20Sopenharmony_ci		}
8568c2ecf20Sopenharmony_ci	}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	for (i = 0 ; i < dev->num_ports; i++) {
8598c2ecf20Sopenharmony_ci		memset(&dev->sriov.alias_guid.ports_guid[i], 0,
8608c2ecf20Sopenharmony_ci		       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
8618c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[i].state_flags |=
8628c2ecf20Sopenharmony_ci				GUID_STATE_NEED_PORT_INIT;
8638c2ecf20Sopenharmony_ci		for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
8648c2ecf20Sopenharmony_ci			/* mark each val as it was deleted */
8658c2ecf20Sopenharmony_ci			memset(dev->sriov.alias_guid.ports_guid[i].
8668c2ecf20Sopenharmony_ci				all_rec_per_port[j].all_recs, 0xFF,
8678c2ecf20Sopenharmony_ci				sizeof(dev->sriov.alias_guid.ports_guid[i].
8688c2ecf20Sopenharmony_ci				all_rec_per_port[j].all_recs));
8698c2ecf20Sopenharmony_ci		}
8708c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
8718c2ecf20Sopenharmony_ci		/*prepare the records, set them to be allocated by sm*/
8728c2ecf20Sopenharmony_ci		if (mlx4_ib_sm_guid_assign)
8738c2ecf20Sopenharmony_ci			for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
8748c2ecf20Sopenharmony_ci				mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
8758c2ecf20Sopenharmony_ci		for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
8768c2ecf20Sopenharmony_ci			invalidate_guid_record(dev, i + 1, j);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
8798c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[i].port  = i;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci		snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
8828c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[i].wq =
8838c2ecf20Sopenharmony_ci			alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
8848c2ecf20Sopenharmony_ci		if (!dev->sriov.alias_guid.ports_guid[i].wq) {
8858c2ecf20Sopenharmony_ci			ret = -ENOMEM;
8868c2ecf20Sopenharmony_ci			goto err_thread;
8878c2ecf20Sopenharmony_ci		}
8888c2ecf20Sopenharmony_ci		INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
8898c2ecf20Sopenharmony_ci			  alias_guid_work);
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci	return 0;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_cierr_thread:
8948c2ecf20Sopenharmony_ci	for (--i; i >= 0; i--) {
8958c2ecf20Sopenharmony_ci		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
8968c2ecf20Sopenharmony_ci		dev->sriov.alias_guid.ports_guid[i].wq = NULL;
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cierr_unregister:
9008c2ecf20Sopenharmony_ci	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
9018c2ecf20Sopenharmony_ci	kfree(dev->sriov.alias_guid.sa_client);
9028c2ecf20Sopenharmony_ci	dev->sriov.alias_guid.sa_client = NULL;
9038c2ecf20Sopenharmony_ci	pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
9048c2ecf20Sopenharmony_ci	return ret;
9058c2ecf20Sopenharmony_ci}
906