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