root/drivers/infiniband/core/agent.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __ib_get_agent_port
  2. ib_get_agent_port
  3. agent_send_response
  4. agent_send_handler
  5. ib_agent_port_open
  6. ib_agent_port_close

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

/* [<][>][^][v][top][bottom][index][help] */