0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include <linux/slab.h>
0040 #include <linux/string.h>
0041
0042 #include "agent.h"
0043 #include "smi.h"
0044 #include "mad_priv.h"
0045
0046 #define SPFX "ib_agent: "
0047
0048 struct ib_agent_port_private {
0049 struct list_head port_list;
0050 struct ib_mad_agent *agent[2];
0051 };
0052
0053 static DEFINE_SPINLOCK(ib_agent_port_list_lock);
0054 static LIST_HEAD(ib_agent_port_list);
0055
0056 static struct ib_agent_port_private *
0057 __ib_get_agent_port(const struct ib_device *device, int port_num)
0058 {
0059 struct ib_agent_port_private *entry;
0060
0061 list_for_each_entry(entry, &ib_agent_port_list, port_list) {
0062 if (entry->agent[1]->device == device &&
0063 entry->agent[1]->port_num == port_num)
0064 return entry;
0065 }
0066 return NULL;
0067 }
0068
0069 static struct ib_agent_port_private *
0070 ib_get_agent_port(const struct ib_device *device, int port_num)
0071 {
0072 struct ib_agent_port_private *entry;
0073 unsigned long flags;
0074
0075 spin_lock_irqsave(&ib_agent_port_list_lock, flags);
0076 entry = __ib_get_agent_port(device, port_num);
0077 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
0078 return entry;
0079 }
0080
0081 void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh,
0082 const struct ib_wc *wc, const struct ib_device *device,
0083 int port_num, int qpn, size_t resp_mad_len, bool opa)
0084 {
0085 struct ib_agent_port_private *port_priv;
0086 struct ib_mad_agent *agent;
0087 struct ib_mad_send_buf *send_buf;
0088 struct ib_ah *ah;
0089 struct ib_mad_send_wr_private *mad_send_wr;
0090
0091 if (rdma_cap_ib_switch(device))
0092 port_priv = ib_get_agent_port(device, 0);
0093 else
0094 port_priv = ib_get_agent_port(device, port_num);
0095
0096 if (!port_priv) {
0097 dev_err(&device->dev, "Unable to find port agent\n");
0098 return;
0099 }
0100
0101 agent = port_priv->agent[qpn];
0102 ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
0103 if (IS_ERR(ah)) {
0104 dev_err(&device->dev, "ib_create_ah_from_wc error %ld\n",
0105 PTR_ERR(ah));
0106 return;
0107 }
0108
0109 if (opa && mad_hdr->base_version != OPA_MGMT_BASE_VERSION)
0110 resp_mad_len = IB_MGMT_MAD_SIZE;
0111
0112 send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
0113 IB_MGMT_MAD_HDR,
0114 resp_mad_len - IB_MGMT_MAD_HDR,
0115 GFP_KERNEL,
0116 mad_hdr->base_version);
0117 if (IS_ERR(send_buf)) {
0118 dev_err(&device->dev, "ib_create_send_mad error\n");
0119 goto err1;
0120 }
0121
0122 memcpy(send_buf->mad, mad_hdr, resp_mad_len);
0123 send_buf->ah = ah;
0124
0125 if (rdma_cap_ib_switch(device)) {
0126 mad_send_wr = container_of(send_buf,
0127 struct ib_mad_send_wr_private,
0128 send_buf);
0129 mad_send_wr->send_wr.port_num = port_num;
0130 }
0131
0132 if (ib_post_send_mad(send_buf, NULL)) {
0133 dev_err(&device->dev, "ib_post_send_mad error\n");
0134 goto err2;
0135 }
0136 return;
0137 err2:
0138 ib_free_send_mad(send_buf);
0139 err1:
0140 rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
0141 }
0142
0143 static void agent_send_handler(struct ib_mad_agent *mad_agent,
0144 struct ib_mad_send_wc *mad_send_wc)
0145 {
0146 rdma_destroy_ah(mad_send_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE);
0147 ib_free_send_mad(mad_send_wc->send_buf);
0148 }
0149
0150 int ib_agent_port_open(struct ib_device *device, int port_num)
0151 {
0152 struct ib_agent_port_private *port_priv;
0153 unsigned long flags;
0154 int ret;
0155
0156
0157 port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
0158 if (!port_priv) {
0159 ret = -ENOMEM;
0160 goto error1;
0161 }
0162
0163 if (rdma_cap_ib_smi(device, port_num)) {
0164
0165 port_priv->agent[0] = ib_register_mad_agent(device, port_num,
0166 IB_QPT_SMI, NULL, 0,
0167 &agent_send_handler,
0168 NULL, NULL, 0);
0169 if (IS_ERR(port_priv->agent[0])) {
0170 ret = PTR_ERR(port_priv->agent[0]);
0171 goto error2;
0172 }
0173 }
0174
0175
0176 port_priv->agent[1] = ib_register_mad_agent(device, port_num,
0177 IB_QPT_GSI, NULL, 0,
0178 &agent_send_handler,
0179 NULL, NULL, 0);
0180 if (IS_ERR(port_priv->agent[1])) {
0181 ret = PTR_ERR(port_priv->agent[1]);
0182 goto error3;
0183 }
0184
0185 spin_lock_irqsave(&ib_agent_port_list_lock, flags);
0186 list_add_tail(&port_priv->port_list, &ib_agent_port_list);
0187 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
0188
0189 return 0;
0190
0191 error3:
0192 if (port_priv->agent[0])
0193 ib_unregister_mad_agent(port_priv->agent[0]);
0194 error2:
0195 kfree(port_priv);
0196 error1:
0197 return ret;
0198 }
0199
0200 int ib_agent_port_close(struct ib_device *device, int port_num)
0201 {
0202 struct ib_agent_port_private *port_priv;
0203 unsigned long flags;
0204
0205 spin_lock_irqsave(&ib_agent_port_list_lock, flags);
0206 port_priv = __ib_get_agent_port(device, port_num);
0207 if (port_priv == NULL) {
0208 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
0209 dev_err(&device->dev, "Port %d not found\n", port_num);
0210 return -ENODEV;
0211 }
0212 list_del(&port_priv->port_list);
0213 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
0214
0215 ib_unregister_mad_agent(port_priv->agent[1]);
0216 if (port_priv->agent[0])
0217 ib_unregister_mad_agent(port_priv->agent[0]);
0218
0219 kfree(port_priv);
0220 return 0;
0221 }