1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved. 5 * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved. 6 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. 7 * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. 8 * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. 9 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 10 * 11 * This software is available to you under a choice of one of two 12 * licenses. You may choose to be licensed under the terms of the GNU 13 * General Public License (GPL) Version 2, available from the file 14 * COPYING in the main directory of this source tree, or the 15 * OpenIB.org BSD license below: 16 * 17 * Redistribution and use in source and binary forms, with or 18 * without modification, are permitted provided that the following 19 * conditions are met: 20 * 21 * - Redistributions of source code must retain the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer. 24 * 25 * - Redistributions in binary form must reproduce the above 26 * copyright notice, this list of conditions and the following 27 * disclaimer in the documentation and/or other materials 28 * provided with the distribution. 29 * 30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 * SOFTWARE. 38 */ 39 40 #include <sys/cdefs.h> 41 #include <linux/slab.h> 42 #include <linux/string.h> 43 44 #include "agent.h" 45 #include "smi.h" 46 #include "mad_priv.h" 47 48 #define SPFX "ib_agent: " 49 50 struct ib_agent_port_private { 51 struct list_head port_list; 52 struct ib_mad_agent *agent[2]; 53 }; 54 55 static DEFINE_SPINLOCK(ib_agent_port_list_lock); 56 static LIST_HEAD(ib_agent_port_list); 57 58 static struct ib_agent_port_private * 59 __ib_get_agent_port(const struct ib_device *device, int port_num) 60 { 61 struct ib_agent_port_private *entry; 62 63 list_for_each_entry(entry, &ib_agent_port_list, port_list) { 64 if (entry->agent[1]->device == device && 65 entry->agent[1]->port_num == port_num) 66 return entry; 67 } 68 return NULL; 69 } 70 71 static struct ib_agent_port_private * 72 ib_get_agent_port(const struct ib_device *device, int port_num) 73 { 74 struct ib_agent_port_private *entry; 75 unsigned long flags; 76 77 spin_lock_irqsave(&ib_agent_port_list_lock, flags); 78 entry = __ib_get_agent_port(device, port_num); 79 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 80 return entry; 81 } 82 83 void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh, 84 const struct ib_wc *wc, const struct ib_device *device, 85 int port_num, int qpn, size_t resp_mad_len, bool opa) 86 { 87 struct ib_agent_port_private *port_priv; 88 struct ib_mad_agent *agent; 89 struct ib_mad_send_buf *send_buf; 90 struct ib_ah *ah; 91 struct ib_mad_send_wr_private *mad_send_wr; 92 93 if (rdma_cap_ib_switch(device)) 94 port_priv = ib_get_agent_port(device, 0); 95 else 96 port_priv = ib_get_agent_port(device, port_num); 97 98 if (!port_priv) { 99 dev_err(&device->dev, "Unable to find port agent\n"); 100 return; 101 } 102 103 agent = port_priv->agent[qpn]; 104 ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num); 105 if (IS_ERR(ah)) { 106 dev_err(&device->dev, "ib_create_ah_from_wc error %ld\n", 107 PTR_ERR(ah)); 108 return; 109 } 110 111 if (opa && mad_hdr->base_version != OPA_MGMT_BASE_VERSION) 112 resp_mad_len = IB_MGMT_MAD_SIZE; 113 114 send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0, 115 IB_MGMT_MAD_HDR, 116 resp_mad_len - IB_MGMT_MAD_HDR, 117 GFP_KERNEL, 118 mad_hdr->base_version); 119 if (IS_ERR(send_buf)) { 120 dev_err(&device->dev, "ib_create_send_mad error\n"); 121 goto err1; 122 } 123 124 memcpy(send_buf->mad, mad_hdr, resp_mad_len); 125 send_buf->ah = ah; 126 127 if (rdma_cap_ib_switch(device)) { 128 mad_send_wr = container_of(send_buf, 129 struct ib_mad_send_wr_private, 130 send_buf); 131 mad_send_wr->send_wr.port_num = port_num; 132 } 133 134 if (ib_post_send_mad(send_buf, NULL)) { 135 dev_err(&device->dev, "ib_post_send_mad error\n"); 136 goto err2; 137 } 138 return; 139 err2: 140 ib_free_send_mad(send_buf); 141 err1: 142 ib_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE); 143 } 144 145 static void agent_send_handler(struct ib_mad_agent *mad_agent, 146 struct ib_mad_send_wc *mad_send_wc) 147 { 148 ib_destroy_ah(mad_send_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE); 149 ib_free_send_mad(mad_send_wc->send_buf); 150 } 151 152 int ib_agent_port_open(struct ib_device *device, int port_num) 153 { 154 struct ib_agent_port_private *port_priv; 155 unsigned long flags; 156 int ret; 157 158 /* Create new device info */ 159 port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL); 160 if (!port_priv) { 161 dev_err(&device->dev, "No memory for ib_agent_port_private\n"); 162 ret = -ENOMEM; 163 goto error1; 164 } 165 166 if (rdma_cap_ib_smi(device, port_num)) { 167 /* Obtain send only MAD agent for SMI QP */ 168 port_priv->agent[0] = ib_register_mad_agent(device, port_num, 169 IB_QPT_SMI, NULL, 0, 170 &agent_send_handler, 171 NULL, NULL, 0); 172 if (IS_ERR(port_priv->agent[0])) { 173 ret = PTR_ERR(port_priv->agent[0]); 174 goto error2; 175 } 176 } 177 178 /* Obtain send only MAD agent for GSI QP */ 179 port_priv->agent[1] = ib_register_mad_agent(device, port_num, 180 IB_QPT_GSI, NULL, 0, 181 &agent_send_handler, 182 NULL, NULL, 0); 183 if (IS_ERR(port_priv->agent[1])) { 184 ret = PTR_ERR(port_priv->agent[1]); 185 goto error3; 186 } 187 188 spin_lock_irqsave(&ib_agent_port_list_lock, flags); 189 list_add_tail(&port_priv->port_list, &ib_agent_port_list); 190 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 191 192 return 0; 193 194 error3: 195 if (port_priv->agent[0]) 196 ib_unregister_mad_agent(port_priv->agent[0]); 197 error2: 198 kfree(port_priv); 199 error1: 200 return ret; 201 } 202 203 int ib_agent_port_close(struct ib_device *device, int port_num) 204 { 205 struct ib_agent_port_private *port_priv; 206 unsigned long flags; 207 208 spin_lock_irqsave(&ib_agent_port_list_lock, flags); 209 port_priv = __ib_get_agent_port(device, port_num); 210 if (port_priv == NULL) { 211 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 212 dev_err(&device->dev, "Port %d not found\n", port_num); 213 return -ENODEV; 214 } 215 list_del(&port_priv->port_list); 216 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); 217 218 ib_unregister_mad_agent(port_priv->agent[1]); 219 if (port_priv->agent[0]) 220 ib_unregister_mad_agent(port_priv->agent[0]); 221 222 kfree(port_priv); 223 return 0; 224 } 225