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