11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 22a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved. 32a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved. 42a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. 52a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. 61bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. 72a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software is available to you under a choice of one of two 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License (GPL) Version 2, available from the file 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * COPYING in the main directory of this source tree, or the 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OpenIB.org BSD license below: 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Redistribution and use in source and binary forms, with or 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without modification, are permitted provided that the following 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * conditions are met: 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Redistributions of source code must retain the above 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice, this list of conditions and the following 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disclaimer. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Redistributions in binary form must reproduce the above 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice, this list of conditions and the following 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disclaimer in the documentation and/or other materials 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided with the distribution. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SOFTWARE. 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 398c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/slab.h> 408c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/string.h> 418c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau 4234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty#include "agent.h" 4334816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty#include "smi.h" 441bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock#include "mad_priv.h" 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4634816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty#define SPFX "ib_agent: " 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4834816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftystruct ib_agent_port_private { 4934816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct list_head port_list; 5034816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct ib_mad_agent *agent[2]; 5134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty}; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5334816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftystatic DEFINE_SPINLOCK(ib_agent_port_list_lock); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic LIST_HEAD(ib_agent_port_list); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5634816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftystatic struct ib_agent_port_private * 5734816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty__ib_get_agent_port(struct ib_device *device, int port_num) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_agent_port_private *entry; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty list_for_each_entry(entry, &ib_agent_port_list, port_list) { 62fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen if (entry->agent[1]->device == device && 63fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen entry->agent[1]->port_num == port_num) 6434816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty return entry; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6934816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftystatic struct ib_agent_port_private * 7034816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftyib_get_agent_port(struct ib_device *device, int port_num) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_agent_port_private *entry; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&ib_agent_port_list_lock, flags); 7634816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty entry = __ib_get_agent_port(device, port_num); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return entry; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 818fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstockvoid agent_send_response(struct ib_mad *mad, struct ib_grh *grh, 828fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock struct ib_wc *wc, struct ib_device *device, 838fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock int port_num, int qpn) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8534816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct ib_agent_port_private *port_priv; 8634816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct ib_mad_agent *agent; 8734816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct ib_mad_send_buf *send_buf; 8834816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty struct ib_ah *ah; 891bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock struct ib_mad_send_wr_private *mad_send_wr; 901bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock 911bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock if (device->node_type == RDMA_NODE_IB_SWITCH) 921bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock port_priv = ib_get_agent_port(device, 0); 931bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock else 941bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock port_priv = ib_get_agent_port(device, port_num); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9634816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty if (!port_priv) { 9734816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty printk(KERN_ERR SPFX "Unable to find port agent\n"); 988fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock return; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty agent = port_priv->agent[qpn]; 10234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num); 10334816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty if (IS_ERR(ah)) { 1041eba843dd7678b9033a0d1ccff21c21b857de77bMichael Heinz printk(KERN_ERR SPFX "ib_create_ah_from_wc error %ld\n", 1051eba843dd7678b9033a0d1ccff21c21b857de77bMichael Heinz PTR_ERR(ah)); 1068fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock return; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10934816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0, 11034816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, 11134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty GFP_KERNEL); 11234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty if (IS_ERR(send_buf)) { 1138fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock printk(KERN_ERR SPFX "ib_create_send_mad error\n"); 11434816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty goto err1; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11734816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty memcpy(send_buf->mad, mad, sizeof *mad); 11834816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty send_buf->ah = ah; 1191bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock 1201bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock if (device->node_type == RDMA_NODE_IB_SWITCH) { 1211bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock mad_send_wr = container_of(send_buf, 1221bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock struct ib_mad_send_wr_private, 1231bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock send_buf); 1241bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock mad_send_wr->send_wr.wr.ud.port_num = port_num; 1251bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock } 1261bae4dbf9576e563da23927e4078fffbbce67a75Hal Rosenstock 1278fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock if (ib_post_send_mad(send_buf, NULL)) { 1288fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock printk(KERN_ERR SPFX "ib_post_send_mad error\n"); 12934816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty goto err2; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1318fc394b1971241999ef9b022feabf6a164791e3fHal Rosenstock return; 13234816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftyerr2: 13334816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ib_free_send_mad(send_buf); 13434816ad98efe4d47ffd858a0345321f9d85d9420Sean Heftyerr1: 13534816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ib_destroy_ah(ah); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agent_send_handler(struct ib_mad_agent *mad_agent, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_mad_send_wc *mad_send_wc) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ib_destroy_ah(mad_send_wc->send_buf->ah); 14234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ib_free_send_mad(mad_send_wc->send_buf); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ib_agent_port_open(struct ib_device *device, int port_num) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_agent_port_private *port_priv; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 14934816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty int ret; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create new device info */ 152de6eb66b56d9df5ce6bd254994f05e065214e8cdRoland Dreier port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port_priv) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR SPFX "No memory for ib_agent_port_private\n"); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error1; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen if (rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND) { 160fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen /* Obtain send only MAD agent for SMI QP */ 161fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen port_priv->agent[0] = ib_register_mad_agent(device, port_num, 162fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen IB_QPT_SMI, NULL, 0, 163fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen &agent_send_handler, 164fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen NULL, NULL); 165fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen if (IS_ERR(port_priv->agent[0])) { 166fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen ret = PTR_ERR(port_priv->agent[0]); 167fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen goto error2; 168fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty /* Obtain send only MAD agent for GSI QP */ 17234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty port_priv->agent[1] = ib_register_mad_agent(device, port_num, 17334816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty IB_QPT_GSI, NULL, 0, 17434816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty &agent_send_handler, 17534816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty NULL, NULL); 17634816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty if (IS_ERR(port_priv->agent[1])) { 17734816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ret = PTR_ERR(port_priv->agent[1]); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error3; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&ib_agent_port_list_lock, flags); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&port_priv->port_list, &ib_agent_port_list); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror3: 188fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen if (port_priv->agent[0]) 189fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen ib_unregister_mad_agent(port_priv->agent[0]); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror2: 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(port_priv); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror1: 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ib_agent_port_close(struct ib_device *device, int port_num) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_agent_port_private *port_priv; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&ib_agent_port_list_lock, flags); 20234816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty port_priv = __ib_get_agent_port(device, port_num); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port_priv == NULL) { 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR SPFX "Port %d not found\n", port_num); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&port_priv->port_list); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21134816ad98efe4d47ffd858a0345321f9d85d9420Sean Hefty ib_unregister_mad_agent(port_priv->agent[1]); 212fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen if (port_priv->agent[0]) 213fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen ib_unregister_mad_agent(port_priv->agent[0]); 214fac70d51914674ce8ae742ed73441ddb4770ad20Eli Cohen 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(port_priv); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 218