[IB] Fix MAD layer DMA mappings to avoid touching data buffer once mapped

The MAD layer was violating the DMA API by touching data buffers used
for sends after the DMA mapping was done.  This causes problems on
non-cache-coherent architectures, because the device doing DMA won't
see updates to the payload buffers that exist only in the CPU cache.

Fix this by having all MAD consumers use ib_create_send_mad() to
allocate their send buffers, and moving the DMA mapping into the MAD
layer so it can be done just before calling send (and after any
modifications of the send buffer by the MAD layer).

Tested on a non-cache-coherent PowerPC 440SPe system.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Sean Hefty 2005-10-25 10:51:39 -07:00 committed by Roland Dreier
parent ae7971a770
commit 34816ad98e
14 changed files with 475 additions and 844 deletions

View File

@ -37,58 +37,41 @@
* $Id: agent.c 1389 2004-12-27 22:56:47Z roland $ * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
*/ */
#include <linux/dma-mapping.h>
#include <asm/bug.h>
#include <rdma/ib_smi.h>
#include "smi.h"
#include "agent_priv.h"
#include "mad_priv.h"
#include "agent.h" #include "agent.h"
#include "smi.h"
spinlock_t ib_agent_port_list_lock; #define SPFX "ib_agent: "
struct ib_agent_port_private {
struct list_head port_list;
struct ib_mad_agent *agent[2];
};
static DEFINE_SPINLOCK(ib_agent_port_list_lock);
static LIST_HEAD(ib_agent_port_list); static LIST_HEAD(ib_agent_port_list);
/* static struct ib_agent_port_private *
* Caller must hold ib_agent_port_list_lock __ib_get_agent_port(struct ib_device *device, int port_num)
*/
static inline struct ib_agent_port_private *
__ib_get_agent_port(struct ib_device *device, int port_num,
struct ib_mad_agent *mad_agent)
{ {
struct ib_agent_port_private *entry; struct ib_agent_port_private *entry;
BUG_ON(!(!!device ^ !!mad_agent)); /* Exactly one MUST be (!NULL) */ list_for_each_entry(entry, &ib_agent_port_list, port_list) {
if (entry->agent[0]->device == device &&
if (device) { entry->agent[0]->port_num == port_num)
list_for_each_entry(entry, &ib_agent_port_list, port_list) { return entry;
if (entry->smp_agent->device == device &&
entry->port_num == port_num)
return entry;
}
} else {
list_for_each_entry(entry, &ib_agent_port_list, port_list) {
if ((entry->smp_agent == mad_agent) ||
(entry->perf_mgmt_agent == mad_agent))
return entry;
}
} }
return NULL; return NULL;
} }
static inline struct ib_agent_port_private * static struct ib_agent_port_private *
ib_get_agent_port(struct ib_device *device, int port_num, ib_get_agent_port(struct ib_device *device, int port_num)
struct ib_mad_agent *mad_agent)
{ {
struct ib_agent_port_private *entry; struct ib_agent_port_private *entry;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ib_agent_port_list_lock, flags); spin_lock_irqsave(&ib_agent_port_list_lock, flags);
entry = __ib_get_agent_port(device, port_num, mad_agent); entry = __ib_get_agent_port(device, port_num);
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
return entry; return entry;
} }
@ -100,192 +83,76 @@ int smi_check_local_dr_smp(struct ib_smp *smp,
if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
return 1; return 1;
port_priv = ib_get_agent_port(device, port_num, NULL);
port_priv = ib_get_agent_port(device, port_num);
if (!port_priv) { if (!port_priv) {
printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d " printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d "
"not open\n", "not open\n", device->name, port_num);
device->name, port_num);
return 1; return 1;
} }
return smi_check_local_smp(port_priv->smp_agent, smp); return smi_check_local_smp(port_priv->agent[0], smp);
} }
static int agent_mad_send(struct ib_mad_agent *mad_agent, int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
struct ib_agent_port_private *port_priv, struct ib_wc *wc, struct ib_device *device,
struct ib_mad_private *mad_priv, int port_num, int qpn)
struct ib_grh *grh,
struct ib_wc *wc)
{
struct ib_agent_send_wr *agent_send_wr;
struct ib_sge gather_list;
struct ib_send_wr send_wr;
struct ib_send_wr *bad_send_wr;
struct ib_ah_attr ah_attr;
unsigned long flags;
int ret = 1;
agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);
if (!agent_send_wr)
goto out;
agent_send_wr->mad = mad_priv;
gather_list.addr = dma_map_single(mad_agent->device->dma_device,
&mad_priv->mad,
sizeof(mad_priv->mad),
DMA_TO_DEVICE);
gather_list.length = sizeof(mad_priv->mad);
gather_list.lkey = mad_agent->mr->lkey;
send_wr.next = NULL;
send_wr.opcode = IB_WR_SEND;
send_wr.sg_list = &gather_list;
send_wr.num_sge = 1;
send_wr.wr.ud.remote_qpn = wc->src_qp; /* DQPN */
send_wr.wr.ud.timeout_ms = 0;
send_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_SOLICITED;
ah_attr.dlid = wc->slid;
ah_attr.port_num = mad_agent->port_num;
ah_attr.src_path_bits = wc->dlid_path_bits;
ah_attr.sl = wc->sl;
ah_attr.static_rate = 0;
ah_attr.ah_flags = 0; /* No GRH */
if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
if (wc->wc_flags & IB_WC_GRH) {
ah_attr.ah_flags = IB_AH_GRH;
/* Should sgid be looked up ? */
ah_attr.grh.sgid_index = 0;
ah_attr.grh.hop_limit = grh->hop_limit;
ah_attr.grh.flow_label = be32_to_cpu(
grh->version_tclass_flow) & 0xfffff;
ah_attr.grh.traffic_class = (be32_to_cpu(
grh->version_tclass_flow) >> 20) & 0xff;
memcpy(ah_attr.grh.dgid.raw,
grh->sgid.raw,
sizeof(ah_attr.grh.dgid));
}
}
agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);
if (IS_ERR(agent_send_wr->ah)) {
printk(KERN_ERR SPFX "No memory for address handle\n");
kfree(agent_send_wr);
goto out;
}
send_wr.wr.ud.ah = agent_send_wr->ah;
if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
send_wr.wr.ud.pkey_index = wc->pkey_index;
send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;
} else { /* for SMPs */
send_wr.wr.ud.pkey_index = 0;
send_wr.wr.ud.remote_qkey = 0;
}
send_wr.wr.ud.mad_hdr = &mad_priv->mad.mad.mad_hdr;
send_wr.wr_id = (unsigned long)agent_send_wr;
pci_unmap_addr_set(agent_send_wr, mapping, gather_list.addr);
/* Send */
spin_lock_irqsave(&port_priv->send_list_lock, flags);
if (ib_post_send_mad(mad_agent, &send_wr, &bad_send_wr)) {
spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
dma_unmap_single(mad_agent->device->dma_device,
pci_unmap_addr(agent_send_wr, mapping),
sizeof(mad_priv->mad),
DMA_TO_DEVICE);
ib_destroy_ah(agent_send_wr->ah);
kfree(agent_send_wr);
} else {
list_add_tail(&agent_send_wr->send_list,
&port_priv->send_posted_list);
spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
ret = 0;
}
out:
return ret;
}
int agent_send(struct ib_mad_private *mad,
struct ib_grh *grh,
struct ib_wc *wc,
struct ib_device *device,
int port_num)
{ {
struct ib_agent_port_private *port_priv; struct ib_agent_port_private *port_priv;
struct ib_mad_agent *mad_agent; struct ib_mad_agent *agent;
struct ib_mad_send_buf *send_buf;
struct ib_ah *ah;
int ret;
port_priv = ib_get_agent_port(device, port_num, NULL); port_priv = ib_get_agent_port(device, port_num);
if (!port_priv) { if (!port_priv) {
printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n", printk(KERN_ERR SPFX "Unable to find port agent\n");
device->name, port_num); return -ENODEV;
return 1;
} }
/* Get mad agent based on mgmt_class in MAD */ agent = port_priv->agent[qpn];
switch (mad->mad.mad.mad_hdr.mgmt_class) { ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: if (IS_ERR(ah)) {
case IB_MGMT_CLASS_SUBN_LID_ROUTED: ret = PTR_ERR(ah);
mad_agent = port_priv->smp_agent; printk(KERN_ERR SPFX "ib_create_ah_from_wc error:%d\n", ret);
break; return ret;
case IB_MGMT_CLASS_PERF_MGMT:
mad_agent = port_priv->perf_mgmt_agent;
break;
default:
return 1;
} }
return agent_mad_send(mad_agent, port_priv, mad, grh, wc); send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_KERNEL);
if (IS_ERR(send_buf)) {
ret = PTR_ERR(send_buf);
printk(KERN_ERR SPFX "ib_create_send_mad error:%d\n", ret);
goto err1;
}
memcpy(send_buf->mad, mad, sizeof *mad);
send_buf->ah = ah;
if ((ret = ib_post_send_mad(send_buf, NULL))) {
printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
goto err2;
}
return 0;
err2:
ib_free_send_mad(send_buf);
err1:
ib_destroy_ah(ah);
return ret;
} }
static void agent_send_handler(struct ib_mad_agent *mad_agent, static void agent_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc) struct ib_mad_send_wc *mad_send_wc)
{ {
struct ib_agent_port_private *port_priv; ib_destroy_ah(mad_send_wc->send_buf->ah);
struct ib_agent_send_wr *agent_send_wr; ib_free_send_mad(mad_send_wc->send_buf);
unsigned long flags;
/* Find matching MAD agent */
port_priv = ib_get_agent_port(NULL, 0, mad_agent);
if (!port_priv) {
printk(KERN_ERR SPFX "agent_send_handler: no matching MAD "
"agent %p\n", mad_agent);
return;
}
agent_send_wr = (struct ib_agent_send_wr *)(unsigned long)mad_send_wc->wr_id;
spin_lock_irqsave(&port_priv->send_list_lock, flags);
/* Remove completed send from posted send MAD list */
list_del(&agent_send_wr->send_list);
spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
dma_unmap_single(mad_agent->device->dma_device,
pci_unmap_addr(agent_send_wr, mapping),
sizeof(agent_send_wr->mad->mad),
DMA_TO_DEVICE);
ib_destroy_ah(agent_send_wr->ah);
/* Release allocated memory */
kmem_cache_free(ib_mad_cache, agent_send_wr->mad);
kfree(agent_send_wr);
} }
int ib_agent_port_open(struct ib_device *device, int port_num) int ib_agent_port_open(struct ib_device *device, int port_num)
{ {
int ret;
struct ib_agent_port_private *port_priv; struct ib_agent_port_private *port_priv;
unsigned long flags; unsigned long flags;
int ret;
/* First, check if port already open for SMI */
port_priv = ib_get_agent_port(device, port_num, NULL);
if (port_priv) {
printk(KERN_DEBUG SPFX "%s port %d already open\n",
device->name, port_num);
return 0;
}
/* Create new device info */ /* Create new device info */
port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL); port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);
@ -294,32 +161,25 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
ret = -ENOMEM; ret = -ENOMEM;
goto error1; goto error1;
} }
memset(port_priv, 0, sizeof *port_priv); memset(port_priv, 0, sizeof *port_priv);
port_priv->port_num = port_num;
spin_lock_init(&port_priv->send_list_lock);
INIT_LIST_HEAD(&port_priv->send_posted_list);
/* Obtain send only MAD agent for SM class (SMI QP) */ /* Obtain send only MAD agent for SMI QP */
port_priv->smp_agent = ib_register_mad_agent(device, port_num, port_priv->agent[0] = ib_register_mad_agent(device, port_num,
IB_QPT_SMI, IB_QPT_SMI, NULL, 0,
NULL, 0,
&agent_send_handler, &agent_send_handler,
NULL, NULL); NULL, NULL);
if (IS_ERR(port_priv->agent[0])) {
if (IS_ERR(port_priv->smp_agent)) { ret = PTR_ERR(port_priv->agent[0]);
ret = PTR_ERR(port_priv->smp_agent);
goto error2; goto error2;
} }
/* Obtain send only MAD agent for PerfMgmt class (GSI QP) */ /* Obtain send only MAD agent for GSI QP */
port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num, port_priv->agent[1] = ib_register_mad_agent(device, port_num,
IB_QPT_GSI, IB_QPT_GSI, NULL, 0,
NULL, 0, &agent_send_handler,
&agent_send_handler, NULL, NULL);
NULL, NULL); if (IS_ERR(port_priv->agent[1])) {
if (IS_ERR(port_priv->perf_mgmt_agent)) { ret = PTR_ERR(port_priv->agent[1]);
ret = PTR_ERR(port_priv->perf_mgmt_agent);
goto error3; goto error3;
} }
@ -330,7 +190,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
return 0; return 0;
error3: error3:
ib_unregister_mad_agent(port_priv->smp_agent); ib_unregister_mad_agent(port_priv->agent[0]);
error2: error2:
kfree(port_priv); kfree(port_priv);
error1: error1:
@ -343,7 +203,7 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ib_agent_port_list_lock, flags); spin_lock_irqsave(&ib_agent_port_list_lock, flags);
port_priv = __ib_get_agent_port(device, port_num, NULL); port_priv = __ib_get_agent_port(device, port_num);
if (port_priv == NULL) { if (port_priv == NULL) {
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
printk(KERN_ERR SPFX "Port %d not found\n", port_num); printk(KERN_ERR SPFX "Port %d not found\n", port_num);
@ -352,9 +212,8 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
list_del(&port_priv->port_list); list_del(&port_priv->port_list);
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags); spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
ib_unregister_mad_agent(port_priv->perf_mgmt_agent); ib_unregister_mad_agent(port_priv->agent[1]);
ib_unregister_mad_agent(port_priv->smp_agent); ib_unregister_mad_agent(port_priv->agent[0]);
kfree(port_priv); kfree(port_priv);
return 0; return 0;
} }

View File

@ -39,17 +39,14 @@
#ifndef __AGENT_H_ #ifndef __AGENT_H_
#define __AGENT_H_ #define __AGENT_H_
extern spinlock_t ib_agent_port_list_lock; #include <rdma/ib_mad.h>
extern int ib_agent_port_open(struct ib_device *device, extern int ib_agent_port_open(struct ib_device *device, int port_num);
int port_num);
extern int ib_agent_port_close(struct ib_device *device, int port_num); extern int ib_agent_port_close(struct ib_device *device, int port_num);
extern int agent_send(struct ib_mad_private *mad, extern int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
struct ib_grh *grh, struct ib_wc *wc, struct ib_device *device,
struct ib_wc *wc, int port_num, int qpn);
struct ib_device *device,
int port_num);
#endif /* __AGENT_H_ */ #endif /* __AGENT_H_ */

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
* Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $
*/
#ifndef __IB_AGENT_PRIV_H__
#define __IB_AGENT_PRIV_H__
#include <linux/pci.h>
#define SPFX "ib_agent: "
struct ib_agent_send_wr {
struct list_head send_list;
struct ib_ah *ah;
struct ib_mad_private *mad;
DECLARE_PCI_UNMAP_ADDR(mapping)
};
struct ib_agent_port_private {
struct list_head port_list;
struct list_head send_posted_list;
spinlock_t send_list_lock;
int port_num;
struct ib_mad_agent *smp_agent; /* SM class */
struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
};
#endif /* __IB_AGENT_PRIV_H__ */

View File

@ -176,8 +176,7 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
cm_id_priv->av.pkey_index, cm_id_priv->av.pkey_index,
ah, 0, sizeof(struct ib_mad_hdr), 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
GFP_ATOMIC); GFP_ATOMIC);
if (IS_ERR(m)) { if (IS_ERR(m)) {
ib_destroy_ah(ah); ib_destroy_ah(ah);
@ -185,7 +184,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
} }
/* Timeout set by caller if response is expected. */ /* Timeout set by caller if response is expected. */
m->send_wr.wr.ud.retries = cm_id_priv->max_cm_retries; m->ah = ah;
m->retries = cm_id_priv->max_cm_retries;
atomic_inc(&cm_id_priv->refcount); atomic_inc(&cm_id_priv->refcount);
m->context[0] = cm_id_priv; m->context[0] = cm_id_priv;
@ -206,20 +206,20 @@ static int cm_alloc_response_msg(struct cm_port *port,
return PTR_ERR(ah); return PTR_ERR(ah);
m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index, m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
ah, 0, sizeof(struct ib_mad_hdr), 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
GFP_ATOMIC); GFP_ATOMIC);
if (IS_ERR(m)) { if (IS_ERR(m)) {
ib_destroy_ah(ah); ib_destroy_ah(ah);
return PTR_ERR(m); return PTR_ERR(m);
} }
m->ah = ah;
*msg = m; *msg = m;
return 0; return 0;
} }
static void cm_free_msg(struct ib_mad_send_buf *msg) static void cm_free_msg(struct ib_mad_send_buf *msg)
{ {
ib_destroy_ah(msg->send_wr.wr.ud.ah); ib_destroy_ah(msg->ah);
if (msg->context[0]) if (msg->context[0])
cm_deref_id(msg->context[0]); cm_deref_id(msg->context[0]);
ib_free_send_mad(msg); ib_free_send_mad(msg);
@ -678,8 +678,7 @@ retest:
break; break;
case IB_CM_SIDR_REQ_SENT: case IB_CM_SIDR_REQ_SENT:
cm_id->state = IB_CM_IDLE; cm_id->state = IB_CM_IDLE;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
break; break;
case IB_CM_SIDR_REQ_RCVD: case IB_CM_SIDR_REQ_RCVD:
@ -690,8 +689,7 @@ retest:
case IB_CM_MRA_REQ_RCVD: case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT: case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD: case IB_CM_MRA_REP_RCVD:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
/* Fall through */ /* Fall through */
case IB_CM_REQ_RCVD: case IB_CM_REQ_RCVD:
case IB_CM_MRA_REQ_SENT: case IB_CM_MRA_REQ_SENT:
@ -708,8 +706,7 @@ retest:
ib_send_cm_dreq(cm_id, NULL, 0); ib_send_cm_dreq(cm_id, NULL, 0);
goto retest; goto retest;
case IB_CM_DREQ_SENT: case IB_CM_DREQ_SENT:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
cm_enter_timewait(cm_id_priv); cm_enter_timewait(cm_id_priv);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
break; break;
@ -883,7 +880,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
struct ib_cm_req_param *param) struct ib_cm_req_param *param)
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_send_wr *bad_send_wr;
struct cm_req_msg *req_msg; struct cm_req_msg *req_msg;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -936,7 +932,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad; req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
cm_format_req(req_msg, cm_id_priv, param); cm_format_req(req_msg, cm_id_priv, param);
cm_id_priv->tid = req_msg->hdr.tid; cm_id_priv->tid = req_msg->hdr.tid;
cm_id_priv->msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms; cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;
cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT; cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;
cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg); cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
@ -945,8 +941,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_req_get_primary_local_ack_timeout(req_msg); cm_req_get_primary_local_ack_timeout(req_msg);
spin_lock_irqsave(&cm_id_priv->lock, flags); spin_lock_irqsave(&cm_id_priv->lock, flags);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(cm_id_priv->msg, NULL);
&cm_id_priv->msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
goto error2; goto error2;
@ -969,7 +964,6 @@ static int cm_issue_rej(struct cm_port *port,
void *ari, u8 ari_length) void *ari, u8 ari_length)
{ {
struct ib_mad_send_buf *msg = NULL; struct ib_mad_send_buf *msg = NULL;
struct ib_send_wr *bad_send_wr;
struct cm_rej_msg *rej_msg, *rcv_msg; struct cm_rej_msg *rej_msg, *rcv_msg;
int ret; int ret;
@ -992,7 +986,7 @@ static int cm_issue_rej(struct cm_port *port,
memcpy(rej_msg->ari, ari, ari_length); memcpy(rej_msg->ari, ari, ari_length);
} }
ret = ib_post_send_mad(port->mad_agent, &msg->send_wr, &bad_send_wr); ret = ib_post_send_mad(msg, NULL);
if (ret) if (ret)
cm_free_msg(msg); cm_free_msg(msg);
@ -1172,7 +1166,6 @@ static void cm_dup_req_handler(struct cm_work *work,
struct cm_id_private *cm_id_priv) struct cm_id_private *cm_id_priv)
{ {
struct ib_mad_send_buf *msg = NULL; struct ib_mad_send_buf *msg = NULL;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1201,8 +1194,7 @@ static void cm_dup_req_handler(struct cm_work *work,
} }
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr, ret = ib_post_send_mad(msg, NULL);
&bad_send_wr);
if (ret) if (ret)
goto free; goto free;
return; return;
@ -1367,7 +1359,6 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct cm_rep_msg *rep_msg; struct cm_rep_msg *rep_msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1389,11 +1380,10 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
rep_msg = (struct cm_rep_msg *) msg->mad; rep_msg = (struct cm_rep_msg *) msg->mad;
cm_format_rep(rep_msg, cm_id_priv, param); cm_format_rep(rep_msg, cm_id_priv, param);
msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms; msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT; msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -1431,7 +1421,6 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
void *data; void *data;
int ret; int ret;
@ -1458,8 +1447,7 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv, cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
private_data, private_data_len); private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -1504,7 +1492,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct cm_rep_msg *rep_msg; struct cm_rep_msg *rep_msg;
struct ib_mad_send_buf *msg = NULL; struct ib_mad_send_buf *msg = NULL;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1532,8 +1519,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
goto unlock; goto unlock;
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr, ret = ib_post_send_mad(msg, NULL);
&bad_send_wr);
if (ret) if (ret)
goto free; goto free;
goto deref; goto deref;
@ -1601,8 +1587,7 @@ static int cm_rep_handler(struct cm_work *work)
/* todo: handle peer_to_peer */ /* todo: handle peer_to_peer */
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count); ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret) if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list); list_add_tail(&work->list, &cm_id_priv->work_list);
@ -1636,8 +1621,7 @@ static int cm_establish_handler(struct cm_work *work)
goto out; goto out;
} }
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count); ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret) if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list); list_add_tail(&work->list, &cm_id_priv->work_list);
@ -1676,8 +1660,7 @@ static int cm_rtu_handler(struct cm_work *work)
} }
cm_id_priv->id.state = IB_CM_ESTABLISHED; cm_id_priv->id.state = IB_CM_ESTABLISHED;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count); ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret) if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list); list_add_tail(&work->list, &cm_id_priv->work_list);
@ -1714,7 +1697,6 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1736,11 +1718,10 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv, cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
private_data, private_data_len); private_data, private_data_len);
msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms; msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT; msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
cm_enter_timewait(cm_id_priv); cm_enter_timewait(cm_id_priv);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@ -1774,7 +1755,6 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
void *data; void *data;
int ret; int ret;
@ -1804,8 +1784,7 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv, cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
private_data, private_data_len); private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr, ret = ib_post_send_mad(msg, NULL);
&bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -1822,7 +1801,6 @@ static int cm_dreq_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct cm_dreq_msg *dreq_msg; struct cm_dreq_msg *dreq_msg;
struct ib_mad_send_buf *msg = NULL; struct ib_mad_send_buf *msg = NULL;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1841,8 +1819,7 @@ static int cm_dreq_handler(struct cm_work *work)
switch (cm_id_priv->id.state) { switch (cm_id_priv->id.state) {
case IB_CM_REP_SENT: case IB_CM_REP_SENT:
case IB_CM_DREQ_SENT: case IB_CM_DREQ_SENT:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
break; break;
case IB_CM_ESTABLISHED: case IB_CM_ESTABLISHED:
case IB_CM_MRA_REP_RCVD: case IB_CM_MRA_REP_RCVD:
@ -1856,8 +1833,7 @@ static int cm_dreq_handler(struct cm_work *work)
cm_id_priv->private_data_len); cm_id_priv->private_data_len);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
if (ib_post_send_mad(cm_id_priv->av.port->mad_agent, if (ib_post_send_mad(msg, NULL))
&msg->send_wr, &bad_send_wr))
cm_free_msg(msg); cm_free_msg(msg);
goto deref; goto deref;
default: default:
@ -1904,8 +1880,7 @@ static int cm_drep_handler(struct cm_work *work)
} }
cm_enter_timewait(cm_id_priv); cm_enter_timewait(cm_id_priv);
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count); ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret) if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list); list_add_tail(&work->list, &cm_id_priv->work_list);
@ -1930,7 +1905,6 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1974,8 +1948,7 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
if (ret) if (ret)
goto out; goto out;
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) if (ret)
cm_free_msg(msg); cm_free_msg(msg);
@ -2051,8 +2024,7 @@ static int cm_rej_handler(struct cm_work *work)
case IB_CM_MRA_REQ_RCVD: case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT: case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD: case IB_CM_MRA_REP_RCVD:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
/* fall through */ /* fall through */
case IB_CM_REQ_RCVD: case IB_CM_REQ_RCVD:
case IB_CM_MRA_REQ_SENT: case IB_CM_MRA_REQ_SENT:
@ -2062,8 +2034,7 @@ static int cm_rej_handler(struct cm_work *work)
cm_reset_to_idle(cm_id_priv); cm_reset_to_idle(cm_id_priv);
break; break;
case IB_CM_DREQ_SENT: case IB_CM_DREQ_SENT:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
/* fall through */ /* fall through */
case IB_CM_REP_RCVD: case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT: case IB_CM_MRA_REP_SENT:
@ -2098,7 +2069,6 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
void *data; void *data;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2122,8 +2092,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv, cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_REQ, service_timeout, CM_MSG_RESPONSE_REQ, service_timeout,
private_data, private_data_len); private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) if (ret)
goto error2; goto error2;
cm_id->state = IB_CM_MRA_REQ_SENT; cm_id->state = IB_CM_MRA_REQ_SENT;
@ -2136,8 +2105,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv, cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_REP, service_timeout, CM_MSG_RESPONSE_REP, service_timeout,
private_data, private_data_len); private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) if (ret)
goto error2; goto error2;
cm_id->state = IB_CM_MRA_REP_SENT; cm_id->state = IB_CM_MRA_REP_SENT;
@ -2150,8 +2118,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv, cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_OTHER, service_timeout, CM_MSG_RESPONSE_OTHER, service_timeout,
private_data, private_data_len); private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) if (ret)
goto error2; goto error2;
cm_id->lap_state = IB_CM_MRA_LAP_SENT; cm_id->lap_state = IB_CM_MRA_LAP_SENT;
@ -2213,14 +2180,14 @@ static int cm_mra_handler(struct cm_work *work)
case IB_CM_REQ_SENT: case IB_CM_REQ_SENT:
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ || if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
ib_modify_mad(cm_id_priv->av.port->mad_agent, ib_modify_mad(cm_id_priv->av.port->mad_agent,
(unsigned long) cm_id_priv->msg, timeout)) cm_id_priv->msg, timeout))
goto out; goto out;
cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD; cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
break; break;
case IB_CM_REP_SENT: case IB_CM_REP_SENT:
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP || if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
ib_modify_mad(cm_id_priv->av.port->mad_agent, ib_modify_mad(cm_id_priv->av.port->mad_agent,
(unsigned long) cm_id_priv->msg, timeout)) cm_id_priv->msg, timeout))
goto out; goto out;
cm_id_priv->id.state = IB_CM_MRA_REP_RCVD; cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
break; break;
@ -2228,7 +2195,7 @@ static int cm_mra_handler(struct cm_work *work)
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER || if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
cm_id_priv->id.lap_state != IB_CM_LAP_SENT || cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
ib_modify_mad(cm_id_priv->av.port->mad_agent, ib_modify_mad(cm_id_priv->av.port->mad_agent,
(unsigned long) cm_id_priv->msg, timeout)) cm_id_priv->msg, timeout))
goto out; goto out;
cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD; cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
break; break;
@ -2291,7 +2258,6 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2312,11 +2278,10 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv, cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,
alternate_path, private_data, private_data_len); alternate_path, private_data, private_data_len);
msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms; msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED; msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -2360,7 +2325,6 @@ static int cm_lap_handler(struct cm_work *work)
struct cm_lap_msg *lap_msg; struct cm_lap_msg *lap_msg;
struct ib_cm_lap_event_param *param; struct ib_cm_lap_event_param *param;
struct ib_mad_send_buf *msg = NULL; struct ib_mad_send_buf *msg = NULL;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2394,8 +2358,7 @@ static int cm_lap_handler(struct cm_work *work)
cm_id_priv->private_data_len); cm_id_priv->private_data_len);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
if (ib_post_send_mad(cm_id_priv->av.port->mad_agent, if (ib_post_send_mad(msg, NULL))
&msg->send_wr, &bad_send_wr))
cm_free_msg(msg); cm_free_msg(msg);
goto deref; goto deref;
default: default:
@ -2451,7 +2414,6 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2474,8 +2436,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status, cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,
info, info_length, private_data, private_data_len); info, info_length, private_data, private_data_len);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -2514,8 +2475,7 @@ static int cm_apr_handler(struct cm_work *work)
goto out; goto out;
} }
cm_id_priv->id.lap_state = IB_CM_LAP_IDLE; cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
cm_id_priv->msg = NULL; cm_id_priv->msg = NULL;
ret = atomic_inc_and_test(&cm_id_priv->work_count); ret = atomic_inc_and_test(&cm_id_priv->work_count);
@ -2590,7 +2550,6 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2613,13 +2572,12 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv, cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,
param); param);
msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms; msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT; msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;
spin_lock_irqsave(&cm_id_priv->lock, flags); spin_lock_irqsave(&cm_id_priv->lock, flags);
if (cm_id->state == IB_CM_IDLE) if (cm_id->state == IB_CM_IDLE)
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
else else
ret = -EINVAL; ret = -EINVAL;
@ -2733,7 +2691,6 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
{ {
struct cm_id_private *cm_id_priv; struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -2755,8 +2712,7 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv, cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
param); param);
ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, ret = ib_post_send_mad(msg, NULL);
&msg->send_wr, &bad_send_wr);
if (ret) { if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg); cm_free_msg(msg);
@ -2809,8 +2765,7 @@ static int cm_sidr_rep_handler(struct cm_work *work)
goto out; goto out;
} }
cm_id_priv->id.state = IB_CM_IDLE; cm_id_priv->id.state = IB_CM_IDLE;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
(unsigned long) cm_id_priv->msg);
spin_unlock_irqrestore(&cm_id_priv->lock, flags); spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_format_sidr_rep_event(work); cm_format_sidr_rep_event(work);
@ -2878,9 +2833,7 @@ discard:
static void cm_send_handler(struct ib_mad_agent *mad_agent, static void cm_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc) struct ib_mad_send_wc *mad_send_wc)
{ {
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
msg = (struct ib_mad_send_buf *)(unsigned long)mad_send_wc->wr_id;
switch (mad_send_wc->status) { switch (mad_send_wc->status) {
case IB_WC_SUCCESS: case IB_WC_SUCCESS:

View File

@ -579,7 +579,7 @@ static void dequeue_mad(struct ib_mad_list_head *mad_list)
} }
static void snoop_send(struct ib_mad_qp_info *qp_info, static void snoop_send(struct ib_mad_qp_info *qp_info,
struct ib_send_wr *send_wr, struct ib_mad_send_buf *send_buf,
struct ib_mad_send_wc *mad_send_wc, struct ib_mad_send_wc *mad_send_wc,
int mad_snoop_flags) int mad_snoop_flags)
{ {
@ -597,7 +597,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
atomic_inc(&mad_snoop_priv->refcount); atomic_inc(&mad_snoop_priv->refcount);
spin_unlock_irqrestore(&qp_info->snoop_lock, flags); spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent, mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
send_wr, mad_send_wc); send_buf, mad_send_wc);
if (atomic_dec_and_test(&mad_snoop_priv->refcount)) if (atomic_dec_and_test(&mad_snoop_priv->refcount))
wake_up(&mad_snoop_priv->wait); wake_up(&mad_snoop_priv->wait);
spin_lock_irqsave(&qp_info->snoop_lock, flags); spin_lock_irqsave(&qp_info->snoop_lock, flags);
@ -654,10 +654,10 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
* Return < 0 if error * Return < 0 if error
*/ */
static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_smp *smp, struct ib_mad_send_wr_private *mad_send_wr)
struct ib_send_wr *send_wr)
{ {
int ret; int ret;
struct ib_smp *smp = mad_send_wr->send_buf.mad;
unsigned long flags; unsigned long flags;
struct ib_mad_local_private *local; struct ib_mad_local_private *local;
struct ib_mad_private *mad_priv; struct ib_mad_private *mad_priv;
@ -666,6 +666,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_device *device = mad_agent_priv->agent.device; struct ib_device *device = mad_agent_priv->agent.device;
u8 port_num = mad_agent_priv->agent.port_num; u8 port_num = mad_agent_priv->agent.port_num;
struct ib_wc mad_wc; struct ib_wc mad_wc;
struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) { if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
ret = -EINVAL; ret = -EINVAL;
@ -745,13 +746,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
goto out; goto out;
} }
local->send_wr = *send_wr; local->mad_send_wr = mad_send_wr;
local->send_wr.sg_list = local->sg_list;
memcpy(local->sg_list, send_wr->sg_list,
sizeof *send_wr->sg_list * send_wr->num_sge);
local->send_wr.next = NULL;
local->tid = send_wr->wr.ud.mad_hdr->tid;
local->wr_id = send_wr->wr_id;
/* Reference MAD agent until send side of local completion handled */ /* Reference MAD agent until send side of local completion handled */
atomic_inc(&mad_agent_priv->refcount); atomic_inc(&mad_agent_priv->refcount);
/* Queue local completion to local list */ /* Queue local completion to local list */
@ -781,17 +776,17 @@ static int get_buf_length(int hdr_len, int data_len)
struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
u32 remote_qpn, u16 pkey_index, u32 remote_qpn, u16 pkey_index,
struct ib_ah *ah, int rmpp_active, int rmpp_active,
int hdr_len, int data_len, int hdr_len, int data_len,
gfp_t gfp_mask) gfp_t gfp_mask)
{ {
struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_buf *send_buf; struct ib_mad_send_wr_private *mad_send_wr;
int buf_size; int buf_size;
void *buf; void *buf;
mad_agent_priv = container_of(mad_agent, mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
struct ib_mad_agent_private, agent); agent);
buf_size = get_buf_length(hdr_len, data_len); buf_size = get_buf_length(hdr_len, data_len);
if ((!mad_agent->rmpp_version && if ((!mad_agent->rmpp_version &&
@ -799,45 +794,40 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
(!rmpp_active && buf_size > sizeof(struct ib_mad))) (!rmpp_active && buf_size > sizeof(struct ib_mad)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
buf = kmalloc(sizeof *send_buf + buf_size, gfp_mask); buf = kmalloc(sizeof *mad_send_wr + buf_size, gfp_mask);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
memset(buf, 0, sizeof *send_buf + buf_size); memset(buf, 0, sizeof *mad_send_wr + buf_size);
send_buf = buf + buf_size; mad_send_wr = buf + buf_size;
send_buf->mad = buf; mad_send_wr->send_buf.mad = buf;
send_buf->sge.addr = dma_map_single(mad_agent->device->dma_device, mad_send_wr->mad_agent_priv = mad_agent_priv;
buf, buf_size, DMA_TO_DEVICE); mad_send_wr->sg_list[0].length = buf_size;
pci_unmap_addr_set(send_buf, mapping, send_buf->sge.addr); mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;
send_buf->sge.length = buf_size;
send_buf->sge.lkey = mad_agent->mr->lkey;
send_buf->send_wr.wr_id = (unsigned long) send_buf; mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
send_buf->send_wr.sg_list = &send_buf->sge; mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
send_buf->send_wr.num_sge = 1; mad_send_wr->send_wr.num_sge = 1;
send_buf->send_wr.opcode = IB_WR_SEND; mad_send_wr->send_wr.opcode = IB_WR_SEND;
send_buf->send_wr.send_flags = IB_SEND_SIGNALED; mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
send_buf->send_wr.wr.ud.ah = ah; mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
send_buf->send_wr.wr.ud.mad_hdr = &send_buf->mad->mad_hdr; mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
send_buf->send_wr.wr.ud.remote_qpn = remote_qpn; mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
send_buf->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
send_buf->send_wr.wr.ud.pkey_index = pkey_index;
if (rmpp_active) { if (rmpp_active) {
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad;
rmpp_mad = (struct ib_rmpp_mad *)send_buf->mad;
rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -
offsetof(struct ib_rmpp_mad, data) + data_len); IB_MGMT_RMPP_HDR + data_len);
rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version; rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;
rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA; rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,
IB_MGMT_RMPP_FLAG_ACTIVE); IB_MGMT_RMPP_FLAG_ACTIVE);
} }
send_buf->mad_agent = mad_agent; mad_send_wr->send_buf.mad_agent = mad_agent;
atomic_inc(&mad_agent_priv->refcount); atomic_inc(&mad_agent_priv->refcount);
return send_buf; return &mad_send_wr->send_buf;
} }
EXPORT_SYMBOL(ib_create_send_mad); EXPORT_SYMBOL(ib_create_send_mad);
@ -847,10 +837,6 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
mad_agent_priv = container_of(send_buf->mad_agent, mad_agent_priv = container_of(send_buf->mad_agent,
struct ib_mad_agent_private, agent); struct ib_mad_agent_private, agent);
dma_unmap_single(send_buf->mad_agent->device->dma_device,
pci_unmap_addr(send_buf, mapping),
send_buf->sge.length, DMA_TO_DEVICE);
kfree(send_buf->mad); kfree(send_buf->mad);
if (atomic_dec_and_test(&mad_agent_priv->refcount)) if (atomic_dec_and_test(&mad_agent_priv->refcount))
@ -861,8 +847,10 @@ EXPORT_SYMBOL(ib_free_send_mad);
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
{ {
struct ib_mad_qp_info *qp_info; struct ib_mad_qp_info *qp_info;
struct ib_send_wr *bad_send_wr;
struct list_head *list; struct list_head *list;
struct ib_send_wr *bad_send_wr;
struct ib_mad_agent *mad_agent;
struct ib_sge *sge;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -871,10 +859,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list; mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
mad_send_wr->mad_list.mad_queue = &qp_info->send_queue; mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
mad_agent = mad_send_wr->send_buf.mad_agent;
sge = mad_send_wr->sg_list;
sge->addr = dma_map_single(mad_agent->device->dma_device,
mad_send_wr->send_buf.mad, sge->length,
DMA_TO_DEVICE);
pci_unmap_addr_set(mad_send_wr, mapping, sge->addr);
spin_lock_irqsave(&qp_info->send_queue.lock, flags); spin_lock_irqsave(&qp_info->send_queue.lock, flags);
if (qp_info->send_queue.count < qp_info->send_queue.max_active) { if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
ret = ib_post_send(mad_send_wr->mad_agent_priv->agent.qp, ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
&mad_send_wr->send_wr, &bad_send_wr); &bad_send_wr);
list = &qp_info->send_queue.list; list = &qp_info->send_queue.list;
} else { } else {
ret = 0; ret = 0;
@ -886,6 +881,11 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
list_add_tail(&mad_send_wr->mad_list.list, list); list_add_tail(&mad_send_wr->mad_list.list, list);
} }
spin_unlock_irqrestore(&qp_info->send_queue.lock, flags); spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
if (ret)
dma_unmap_single(mad_agent->device->dma_device,
pci_unmap_addr(mad_send_wr, mapping),
sge->length, DMA_TO_DEVICE);
return ret; return ret;
} }
@ -893,45 +893,28 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
* ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
* with the registered client * with the registered client
*/ */
int ib_post_send_mad(struct ib_mad_agent *mad_agent, int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
struct ib_send_wr *send_wr, struct ib_mad_send_buf **bad_send_buf)
struct ib_send_wr **bad_send_wr)
{ {
int ret = -EINVAL;
struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_buf *next_send_buf;
/* Validate supplied parameters */ struct ib_mad_send_wr_private *mad_send_wr;
if (!bad_send_wr) unsigned long flags;
goto error1; int ret = -EINVAL;
if (!mad_agent || !send_wr)
goto error2;
if (!mad_agent->send_handler)
goto error2;
mad_agent_priv = container_of(mad_agent,
struct ib_mad_agent_private,
agent);
/* Walk list of send WRs and post each on send list */ /* Walk list of send WRs and post each on send list */
while (send_wr) { for (; send_buf; send_buf = next_send_buf) {
unsigned long flags;
struct ib_send_wr *next_send_wr;
struct ib_mad_send_wr_private *mad_send_wr;
struct ib_smp *smp;
/* Validate more parameters */ mad_send_wr = container_of(send_buf,
if (send_wr->num_sge > IB_MAD_SEND_REQ_MAX_SG) struct ib_mad_send_wr_private,
goto error2; send_buf);
mad_agent_priv = mad_send_wr->mad_agent_priv;
if (send_wr->wr.ud.timeout_ms && !mad_agent->recv_handler) if (!send_buf->mad_agent->send_handler ||
goto error2; (send_buf->timeout_ms &&
!send_buf->mad_agent->recv_handler)) {
if (!send_wr->wr.ud.mad_hdr) { ret = -EINVAL;
printk(KERN_ERR PFX "MAD header must be supplied " goto error;
"in WR %p\n", send_wr);
goto error2;
} }
/* /*
@ -939,40 +922,24 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
* current one completes, and the user modifies the work * current one completes, and the user modifies the work
* request associated with the completion * request associated with the completion
*/ */
next_send_wr = (struct ib_send_wr *)send_wr->next; next_send_buf = send_buf->next;
mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
smp = (struct ib_smp *)send_wr->wr.ud.mad_hdr; if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
ret = handle_outgoing_dr_smp(mad_agent_priv, smp, ret = handle_outgoing_dr_smp(mad_agent_priv,
send_wr); mad_send_wr);
if (ret < 0) /* error */ if (ret < 0) /* error */
goto error2; goto error;
else if (ret == 1) /* locally consumed */ else if (ret == 1) /* locally consumed */
goto next; continue;
} }
/* Allocate MAD send WR tracking structure */ mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
mad_send_wr = kmalloc(sizeof *mad_send_wr, GFP_ATOMIC);
if (!mad_send_wr) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_send_wr_private\n");
ret = -ENOMEM;
goto error2;
}
memset(mad_send_wr, 0, sizeof *mad_send_wr);
mad_send_wr->send_wr = *send_wr;
mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
memcpy(mad_send_wr->sg_list, send_wr->sg_list,
sizeof *send_wr->sg_list * send_wr->num_sge);
mad_send_wr->wr_id = send_wr->wr_id;
mad_send_wr->tid = send_wr->wr.ud.mad_hdr->tid;
mad_send_wr->mad_agent_priv = mad_agent_priv;
/* Timeout will be updated after send completes */ /* Timeout will be updated after send completes */
mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr. mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
ud.timeout_ms); mad_send_wr->retries = send_buf->retries;
mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries; /* Reference for work request to QP + response */
/* One reference for each work request to QP + response */
mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0); mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
mad_send_wr->status = IB_WC_SUCCESS; mad_send_wr->status = IB_WC_SUCCESS;
@ -995,16 +962,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
list_del(&mad_send_wr->agent_list); list_del(&mad_send_wr->agent_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags); spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
atomic_dec(&mad_agent_priv->refcount); atomic_dec(&mad_agent_priv->refcount);
goto error2; goto error;
} }
next:
send_wr = next_send_wr;
} }
return 0; return 0;
error:
error2: if (bad_send_buf)
*bad_send_wr = send_wr; *bad_send_buf = send_buf;
error1:
return ret; return ret;
} }
EXPORT_SYMBOL(ib_post_send_mad); EXPORT_SYMBOL(ib_post_send_mad);
@ -1447,8 +1411,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
* of MAD. * of MAD.
*/ */
hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32; hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32;
list_for_each_entry(entry, &port_priv->agent_list, list_for_each_entry(entry, &port_priv->agent_list, agent_list) {
agent_list) {
if (entry->agent.hi_tid == hi_tid) { if (entry->agent.hi_tid == hi_tid) {
mad_agent = entry; mad_agent = entry;
break; break;
@ -1571,8 +1534,7 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
*/ */
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) { agent_list) {
if (is_data_mad(mad_agent_priv, if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
mad_send_wr->send_wr.wr.ud.mad_hdr) &&
mad_send_wr->tid == tid && mad_send_wr->timeout) { mad_send_wr->tid == tid && mad_send_wr->timeout) {
/* Verify request has not been canceled */ /* Verify request has not been canceled */
return (mad_send_wr->status == IB_WC_SUCCESS) ? return (mad_send_wr->status == IB_WC_SUCCESS) ?
@ -1628,14 +1590,14 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
spin_unlock_irqrestore(&mad_agent_priv->lock, flags); spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
/* Defined behavior is to complete response before request */ /* Defined behavior is to complete response before request */
mad_recv_wc->wc->wr_id = mad_send_wr->wr_id; mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
mad_recv_wc); mad_recv_wc);
atomic_dec(&mad_agent_priv->refcount); atomic_dec(&mad_agent_priv->refcount);
mad_send_wc.status = IB_WC_SUCCESS; mad_send_wc.status = IB_WC_SUCCESS;
mad_send_wc.vendor_err = 0; mad_send_wc.vendor_err = 0;
mad_send_wc.wr_id = mad_send_wr->wr_id; mad_send_wc.send_buf = &mad_send_wr->send_buf;
ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc); ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
} else { } else {
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
@ -1728,11 +1690,11 @@ local:
if (ret & IB_MAD_RESULT_CONSUMED) if (ret & IB_MAD_RESULT_CONSUMED)
goto out; goto out;
if (ret & IB_MAD_RESULT_REPLY) { if (ret & IB_MAD_RESULT_REPLY) {
/* Send response */ agent_send_response(&response->mad.mad,
if (!agent_send(response, &recv->grh, wc, &recv->grh, wc,
port_priv->device, port_priv->device,
port_priv->port_num)) port_priv->port_num,
response = NULL; qp_info->qp->qp_num);
goto out; goto out;
} }
} }
@ -1866,15 +1828,15 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
if (mad_send_wr->status != IB_WC_SUCCESS ) if (mad_send_wr->status != IB_WC_SUCCESS )
mad_send_wc->status = mad_send_wr->status; mad_send_wc->status = mad_send_wr->status;
if (ret != IB_RMPP_RESULT_INTERNAL) if (ret == IB_RMPP_RESULT_INTERNAL)
ib_rmpp_send_handler(mad_send_wc);
else
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
mad_send_wc); mad_send_wc);
/* Release reference on agent taken when sending */ /* Release reference on agent taken when sending */
if (atomic_dec_and_test(&mad_agent_priv->refcount)) if (atomic_dec_and_test(&mad_agent_priv->refcount))
wake_up(&mad_agent_priv->wait); wake_up(&mad_agent_priv->wait);
kfree(mad_send_wr);
return; return;
done: done:
spin_unlock_irqrestore(&mad_agent_priv->lock, flags); spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
@ -1888,6 +1850,7 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
struct ib_mad_qp_info *qp_info; struct ib_mad_qp_info *qp_info;
struct ib_mad_queue *send_queue; struct ib_mad_queue *send_queue;
struct ib_send_wr *bad_send_wr; struct ib_send_wr *bad_send_wr;
struct ib_mad_send_wc mad_send_wc;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -1898,6 +1861,9 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
qp_info = send_queue->qp_info; qp_info = send_queue->qp_info;
retry: retry:
dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
pci_unmap_addr(mad_send_wr, mapping),
mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
queued_send_wr = NULL; queued_send_wr = NULL;
spin_lock_irqsave(&send_queue->lock, flags); spin_lock_irqsave(&send_queue->lock, flags);
list_del(&mad_list->list); list_del(&mad_list->list);
@ -1914,17 +1880,17 @@ retry:
} }
spin_unlock_irqrestore(&send_queue->lock, flags); spin_unlock_irqrestore(&send_queue->lock, flags);
/* Restore client wr_id in WC and complete send */ mad_send_wc.send_buf = &mad_send_wr->send_buf;
wc->wr_id = mad_send_wr->wr_id; mad_send_wc.status = wc->status;
mad_send_wc.vendor_err = wc->vendor_err;
if (atomic_read(&qp_info->snoop_count)) if (atomic_read(&qp_info->snoop_count))
snoop_send(qp_info, &mad_send_wr->send_wr, snoop_send(qp_info, &mad_send_wr->send_buf, &mad_send_wc,
(struct ib_mad_send_wc *)wc,
IB_MAD_SNOOP_SEND_COMPLETIONS); IB_MAD_SNOOP_SEND_COMPLETIONS);
ib_mad_complete_send_wr(mad_send_wr, (struct ib_mad_send_wc *)wc); ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
if (queued_send_wr) { if (queued_send_wr) {
ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr, ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
&bad_send_wr); &bad_send_wr);
if (ret) { if (ret) {
printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret); printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
mad_send_wr = queued_send_wr; mad_send_wr = queued_send_wr;
@ -2066,38 +2032,37 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr, list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
&cancel_list, agent_list) { &cancel_list, agent_list) {
mad_send_wc.wr_id = mad_send_wr->wr_id; mad_send_wc.send_buf = &mad_send_wr->send_buf;
list_del(&mad_send_wr->agent_list);
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc); &mad_send_wc);
list_del(&mad_send_wr->agent_list);
kfree(mad_send_wr);
atomic_dec(&mad_agent_priv->refcount); atomic_dec(&mad_agent_priv->refcount);
} }
} }
static struct ib_mad_send_wr_private* static struct ib_mad_send_wr_private*
find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv, u64 wr_id) find_send_wr(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_send_buf *send_buf)
{ {
struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wr_private *mad_send_wr;
list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
agent_list) { agent_list) {
if (mad_send_wr->wr_id == wr_id) if (&mad_send_wr->send_buf == send_buf)
return mad_send_wr; return mad_send_wr;
} }
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) { agent_list) {
if (is_data_mad(mad_agent_priv, if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
mad_send_wr->send_wr.wr.ud.mad_hdr) && &mad_send_wr->send_buf == send_buf)
mad_send_wr->wr_id == wr_id)
return mad_send_wr; return mad_send_wr;
} }
return NULL; return NULL;
} }
int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms) int ib_modify_mad(struct ib_mad_agent *mad_agent,
struct ib_mad_send_buf *send_buf, u32 timeout_ms)
{ {
struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wr_private *mad_send_wr;
@ -2107,7 +2072,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
agent); agent);
spin_lock_irqsave(&mad_agent_priv->lock, flags); spin_lock_irqsave(&mad_agent_priv->lock, flags);
mad_send_wr = find_send_by_wr_id(mad_agent_priv, wr_id); mad_send_wr = find_send_wr(mad_agent_priv, send_buf);
if (!mad_send_wr || mad_send_wr->status != IB_WC_SUCCESS) { if (!mad_send_wr || mad_send_wr->status != IB_WC_SUCCESS) {
spin_unlock_irqrestore(&mad_agent_priv->lock, flags); spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
return -EINVAL; return -EINVAL;
@ -2119,7 +2084,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
mad_send_wr->refcount -= (mad_send_wr->timeout > 0); mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
} }
mad_send_wr->send_wr.wr.ud.timeout_ms = timeout_ms; mad_send_wr->send_buf.timeout_ms = timeout_ms;
if (active) if (active)
mad_send_wr->timeout = msecs_to_jiffies(timeout_ms); mad_send_wr->timeout = msecs_to_jiffies(timeout_ms);
else else
@ -2130,9 +2095,10 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
} }
EXPORT_SYMBOL(ib_modify_mad); EXPORT_SYMBOL(ib_modify_mad);
void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id) void ib_cancel_mad(struct ib_mad_agent *mad_agent,
struct ib_mad_send_buf *send_buf)
{ {
ib_modify_mad(mad_agent, wr_id, 0); ib_modify_mad(mad_agent, send_buf, 0);
} }
EXPORT_SYMBOL(ib_cancel_mad); EXPORT_SYMBOL(ib_cancel_mad);
@ -2166,10 +2132,9 @@ static void local_completions(void *data)
* Defined behavior is to complete response * Defined behavior is to complete response
* before request * before request
*/ */
build_smp_wc(local->wr_id, build_smp_wc((unsigned long) local->mad_send_wr,
be16_to_cpu(IB_LID_PERMISSIVE), be16_to_cpu(IB_LID_PERMISSIVE),
0 /* pkey index */, 0, recv_mad_agent->agent.port_num, &wc);
recv_mad_agent->agent.port_num, &wc);
local->mad_priv->header.recv_wc.wc = &wc; local->mad_priv->header.recv_wc.wc = &wc;
local->mad_priv->header.recv_wc.mad_len = local->mad_priv->header.recv_wc.mad_len =
@ -2196,11 +2161,11 @@ local_send_completion:
/* Complete send */ /* Complete send */
mad_send_wc.status = IB_WC_SUCCESS; mad_send_wc.status = IB_WC_SUCCESS;
mad_send_wc.vendor_err = 0; mad_send_wc.vendor_err = 0;
mad_send_wc.wr_id = local->wr_id; mad_send_wc.send_buf = &local->mad_send_wr->send_buf;
if (atomic_read(&mad_agent_priv->qp_info->snoop_count)) if (atomic_read(&mad_agent_priv->qp_info->snoop_count))
snoop_send(mad_agent_priv->qp_info, &local->send_wr, snoop_send(mad_agent_priv->qp_info,
&mad_send_wc, &local->mad_send_wr->send_buf,
IB_MAD_SNOOP_SEND_COMPLETIONS); &mad_send_wc, IB_MAD_SNOOP_SEND_COMPLETIONS);
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc); &mad_send_wc);
@ -2221,8 +2186,7 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
if (!mad_send_wr->retries--) if (!mad_send_wr->retries--)
return -ETIMEDOUT; return -ETIMEDOUT;
mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr. mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
wr.ud.timeout_ms);
if (mad_send_wr->mad_agent_priv->agent.rmpp_version) { if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
ret = ib_retry_rmpp(mad_send_wr); ret = ib_retry_rmpp(mad_send_wr);
@ -2285,11 +2249,10 @@ static void timeout_sends(void *data)
mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR; mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
else else
mad_send_wc.status = mad_send_wr->status; mad_send_wc.status = mad_send_wr->status;
mad_send_wc.wr_id = mad_send_wr->wr_id; mad_send_wc.send_buf = &mad_send_wr->send_buf;
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc); &mad_send_wc);
kfree(mad_send_wr);
atomic_dec(&mad_agent_priv->refcount); atomic_dec(&mad_agent_priv->refcount);
spin_lock_irqsave(&mad_agent_priv->lock, flags); spin_lock_irqsave(&mad_agent_priv->lock, flags);
} }
@ -2761,7 +2724,6 @@ static int __init ib_mad_init_module(void)
int ret; int ret;
spin_lock_init(&ib_mad_port_list_lock); spin_lock_init(&ib_mad_port_list_lock);
spin_lock_init(&ib_agent_port_list_lock);
ib_mad_cache = kmem_cache_create("ib_mad", ib_mad_cache = kmem_cache_create("ib_mad",
sizeof(struct ib_mad_private), sizeof(struct ib_mad_private),

View File

@ -118,9 +118,10 @@ struct ib_mad_send_wr_private {
struct ib_mad_list_head mad_list; struct ib_mad_list_head mad_list;
struct list_head agent_list; struct list_head agent_list;
struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_buf send_buf;
DECLARE_PCI_UNMAP_ADDR(mapping)
struct ib_send_wr send_wr; struct ib_send_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
u64 wr_id; /* client WR ID */
__be64 tid; __be64 tid;
unsigned long timeout; unsigned long timeout;
int retries; int retries;
@ -141,10 +142,7 @@ struct ib_mad_local_private {
struct list_head completion_list; struct list_head completion_list;
struct ib_mad_private *mad_priv; struct ib_mad_private *mad_priv;
struct ib_mad_agent_private *recv_mad_agent; struct ib_mad_agent_private *recv_mad_agent;
struct ib_send_wr send_wr; struct ib_mad_send_wr_private *mad_send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
u64 wr_id; /* client WR ID */
__be64 tid;
}; };
struct ib_mad_mgmt_method_table { struct ib_mad_mgmt_method_table {

View File

@ -103,12 +103,12 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
static int data_offset(u8 mgmt_class) static int data_offset(u8 mgmt_class)
{ {
if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
return offsetof(struct ib_sa_mad, data); return IB_MGMT_SA_HDR;
else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
(mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
return offsetof(struct ib_vendor_mad, data); return IB_MGMT_VENDOR_HDR;
else else
return offsetof(struct ib_rmpp_mad, data); return IB_MGMT_RMPP_HDR;
} }
static void format_ack(struct ib_rmpp_mad *ack, static void format_ack(struct ib_rmpp_mad *ack,
@ -135,21 +135,18 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
struct ib_mad_recv_wc *recv_wc) struct ib_mad_recv_wc *recv_wc)
{ {
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_send_wr *bad_send_wr; int ret;
int hdr_len, ret;
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, rmpp_recv->ah, 1, recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR,
hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len, IB_MGMT_RMPP_DATA, GFP_KERNEL);
GFP_KERNEL);
if (!msg) if (!msg)
return; return;
format_ack((struct ib_rmpp_mad *) msg->mad, format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad,
(struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv); rmpp_recv);
ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr, msg->ah = rmpp_recv->ah;
&bad_send_wr); ret = ib_post_send_mad(msg, NULL);
if (ret) if (ret)
ib_free_send_mad(msg); ib_free_send_mad(msg);
} }
@ -160,30 +157,31 @@ static int alloc_response_msg(struct ib_mad_agent *agent,
{ {
struct ib_mad_send_buf *m; struct ib_mad_send_buf *m;
struct ib_ah *ah; struct ib_ah *ah;
int hdr_len;
ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc, ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
recv_wc->recv_buf.grh, agent->port_num); recv_wc->recv_buf.grh, agent->port_num);
if (IS_ERR(ah)) if (IS_ERR(ah))
return PTR_ERR(ah); return PTR_ERR(ah);
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
m = ib_create_send_mad(agent, recv_wc->wc->src_qp, m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, ah, 1, hdr_len, recv_wc->wc->pkey_index, 1,
sizeof(struct ib_rmpp_mad) - hdr_len, IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA, GFP_KERNEL);
GFP_KERNEL);
if (IS_ERR(m)) { if (IS_ERR(m)) {
ib_destroy_ah(ah); ib_destroy_ah(ah);
return PTR_ERR(m); return PTR_ERR(m);
} }
m->ah = ah;
*msg = m; *msg = m;
return 0; return 0;
} }
static void free_msg(struct ib_mad_send_buf *msg) void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc)
{ {
ib_destroy_ah(msg->send_wr.wr.ud.ah); struct ib_rmpp_mad *rmpp_mad = mad_send_wc->send_buf->mad;
ib_free_send_mad(msg);
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_ACK)
ib_destroy_ah(mad_send_wc->send_buf->ah);
ib_free_send_mad(mad_send_wc->send_buf);
} }
static void nack_recv(struct ib_mad_agent_private *agent, static void nack_recv(struct ib_mad_agent_private *agent,
@ -191,14 +189,13 @@ static void nack_recv(struct ib_mad_agent_private *agent,
{ {
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
struct ib_send_wr *bad_send_wr;
int ret; int ret;
ret = alloc_response_msg(&agent->agent, recv_wc, &msg); ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
if (ret) if (ret)
return; return;
rmpp_mad = (struct ib_rmpp_mad *) msg->mad; rmpp_mad = msg->mad;
memcpy(rmpp_mad, recv_wc->recv_buf.mad, memcpy(rmpp_mad, recv_wc->recv_buf.mad,
data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class)); data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
@ -210,9 +207,11 @@ static void nack_recv(struct ib_mad_agent_private *agent,
rmpp_mad->rmpp_hdr.seg_num = 0; rmpp_mad->rmpp_hdr.seg_num = 0;
rmpp_mad->rmpp_hdr.paylen_newwin = 0; rmpp_mad->rmpp_hdr.paylen_newwin = 0;
ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr); ret = ib_post_send_mad(msg, NULL);
if (ret) if (ret) {
free_msg(msg); ib_destroy_ah(msg->ah);
ib_free_send_mad(msg);
}
} }
static void recv_timeout_handler(void *data) static void recv_timeout_handler(void *data)
@ -585,7 +584,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
int timeout; int timeout;
u32 paylen; u32 paylen;
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; rmpp_mad = mad_send_wr->send_buf.mad;
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num); rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num);
@ -612,7 +611,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
} }
/* 2 seconds for an ACK until we can find the packet lifetime */ /* 2 seconds for an ACK until we can find the packet lifetime */
timeout = mad_send_wr->send_wr.wr.ud.timeout_ms; timeout = mad_send_wr->send_buf.timeout_ms;
if (!timeout || timeout > 2000) if (!timeout || timeout > 2000)
mad_send_wr->timeout = msecs_to_jiffies(2000); mad_send_wr->timeout = msecs_to_jiffies(2000);
mad_send_wr->seg_num++; mad_send_wr->seg_num++;
@ -640,7 +639,7 @@ static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
wc.status = IB_WC_REM_ABORT_ERR; wc.status = IB_WC_REM_ABORT_ERR;
wc.vendor_err = rmpp_status; wc.vendor_err = rmpp_status;
wc.wr_id = mad_send_wr->wr_id; wc.send_buf = &mad_send_wr->send_buf;
ib_mad_complete_send_wr(mad_send_wr, &wc); ib_mad_complete_send_wr(mad_send_wr, &wc);
return; return;
out: out:
@ -694,12 +693,12 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
if (seg_num > mad_send_wr->last_ack) { if (seg_num > mad_send_wr->last_ack) {
mad_send_wr->last_ack = seg_num; mad_send_wr->last_ack = seg_num;
mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries; mad_send_wr->retries = mad_send_wr->send_buf.retries;
} }
mad_send_wr->newwin = newwin; mad_send_wr->newwin = newwin;
if (mad_send_wr->last_ack == mad_send_wr->total_seg) { if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
/* If no response is expected, the ACK completes the send */ /* If no response is expected, the ACK completes the send */
if (!mad_send_wr->send_wr.wr.ud.timeout_ms) { if (!mad_send_wr->send_buf.timeout_ms) {
struct ib_mad_send_wc wc; struct ib_mad_send_wc wc;
ib_mark_mad_done(mad_send_wr); ib_mark_mad_done(mad_send_wr);
@ -707,13 +706,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
wc.status = IB_WC_SUCCESS; wc.status = IB_WC_SUCCESS;
wc.vendor_err = 0; wc.vendor_err = 0;
wc.wr_id = mad_send_wr->wr_id; wc.send_buf = &mad_send_wr->send_buf;
ib_mad_complete_send_wr(mad_send_wr, &wc); ib_mad_complete_send_wr(mad_send_wr, &wc);
return; return;
} }
if (mad_send_wr->refcount == 1) if (mad_send_wr->refcount == 1)
ib_reset_mad_timeout(mad_send_wr, mad_send_wr-> ib_reset_mad_timeout(mad_send_wr,
send_wr.wr.ud.timeout_ms); mad_send_wr->send_buf.timeout_ms);
} else if (mad_send_wr->refcount == 1 && } else if (mad_send_wr->refcount == 1 &&
mad_send_wr->seg_num < mad_send_wr->newwin && mad_send_wr->seg_num < mad_send_wr->newwin &&
mad_send_wr->seg_num <= mad_send_wr->total_seg) { mad_send_wr->seg_num <= mad_send_wr->total_seg) {
@ -842,7 +841,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
int i, total_len, ret; int i, total_len, ret;
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE)) IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED; return IB_RMPP_RESULT_UNHANDLED;
@ -863,7 +862,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) / mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
(sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset); (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
mad_send_wr->pad = total_len - offsetof(struct ib_rmpp_mad, data) - mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR -
be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
/* We need to wait for the final ACK even if there isn't a response */ /* We need to wait for the final ACK even if there isn't a response */
@ -878,23 +877,15 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc) struct ib_mad_send_wc *mad_send_wc)
{ {
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
struct ib_mad_send_buf *msg;
int ret; int ret;
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE)) IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */ return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) { if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
msg = (struct ib_mad_send_buf *) (unsigned long)
mad_send_wc->wr_id;
if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
ib_free_send_mad(msg);
else
free_msg(msg);
return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */ return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */
}
if (mad_send_wc->status != IB_WC_SUCCESS || if (mad_send_wc->status != IB_WC_SUCCESS ||
mad_send_wr->status != IB_WC_SUCCESS) mad_send_wr->status != IB_WC_SUCCESS)
@ -905,7 +896,7 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
if (mad_send_wr->last_ack == mad_send_wr->total_seg) { if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
mad_send_wr->timeout = mad_send_wr->timeout =
msecs_to_jiffies(mad_send_wr->send_wr.wr.ud.timeout_ms); msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
return IB_RMPP_RESULT_PROCESSED; /* Send done */ return IB_RMPP_RESULT_PROCESSED; /* Send done */
} }
@ -926,7 +917,7 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr)
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
int ret; int ret;
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE)) IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */ return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */

View File

@ -51,6 +51,8 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr, int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc); struct ib_mad_send_wc *mad_send_wc);
void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc);
void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent); void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent);
int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr); int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr);

View File

@ -73,11 +73,10 @@ struct ib_sa_device {
struct ib_sa_query { struct ib_sa_query {
void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *); void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
void (*release)(struct ib_sa_query *); void (*release)(struct ib_sa_query *);
struct ib_sa_port *port; struct ib_sa_port *port;
struct ib_sa_mad *mad; struct ib_mad_send_buf *mad_buf;
struct ib_sa_sm_ah *sm_ah; struct ib_sa_sm_ah *sm_ah;
DECLARE_PCI_UNMAP_ADDR(mapping) int id;
int id;
}; };
struct ib_sa_service_query { struct ib_sa_service_query {
@ -426,6 +425,7 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
{ {
unsigned long flags; unsigned long flags;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_mad_send_buf *mad_buf;
spin_lock_irqsave(&idr_lock, flags); spin_lock_irqsave(&idr_lock, flags);
if (idr_find(&query_idr, id) != query) { if (idr_find(&query_idr, id) != query) {
@ -433,9 +433,10 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
return; return;
} }
agent = query->port->agent; agent = query->port->agent;
mad_buf = query->mad_buf;
spin_unlock_irqrestore(&idr_lock, flags); spin_unlock_irqrestore(&idr_lock, flags);
ib_cancel_mad(agent, id); ib_cancel_mad(agent, mad_buf);
} }
EXPORT_SYMBOL(ib_sa_cancel_query); EXPORT_SYMBOL(ib_sa_cancel_query);
@ -457,71 +458,46 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
static int send_mad(struct ib_sa_query *query, int timeout_ms) static int send_mad(struct ib_sa_query *query, int timeout_ms)
{ {
struct ib_sa_port *port = query->port;
unsigned long flags; unsigned long flags;
int ret; int ret, id;
struct ib_sge gather_list;
struct ib_send_wr *bad_wr, wr = {
.opcode = IB_WR_SEND,
.sg_list = &gather_list,
.num_sge = 1,
.send_flags = IB_SEND_SIGNALED,
.wr = {
.ud = {
.mad_hdr = &query->mad->mad_hdr,
.remote_qpn = 1,
.remote_qkey = IB_QP1_QKEY,
.timeout_ms = timeout_ms,
}
}
};
retry: retry:
if (!idr_pre_get(&query_idr, GFP_ATOMIC)) if (!idr_pre_get(&query_idr, GFP_ATOMIC))
return -ENOMEM; return -ENOMEM;
spin_lock_irqsave(&idr_lock, flags); spin_lock_irqsave(&idr_lock, flags);
ret = idr_get_new(&query_idr, query, &query->id); ret = idr_get_new(&query_idr, query, &id);
spin_unlock_irqrestore(&idr_lock, flags); spin_unlock_irqrestore(&idr_lock, flags);
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto retry; goto retry;
if (ret) if (ret)
return ret; return ret;
wr.wr_id = query->id; query->mad_buf->timeout_ms = timeout_ms;
query->mad_buf->context[0] = query;
query->id = id;
spin_lock_irqsave(&port->ah_lock, flags); spin_lock_irqsave(&query->port->ah_lock, flags);
kref_get(&port->sm_ah->ref); kref_get(&query->port->sm_ah->ref);
query->sm_ah = port->sm_ah; query->sm_ah = query->port->sm_ah;
wr.wr.ud.ah = port->sm_ah->ah; spin_unlock_irqrestore(&query->port->ah_lock, flags);
spin_unlock_irqrestore(&port->ah_lock, flags);
gather_list.addr = dma_map_single(port->agent->device->dma_device, query->mad_buf->ah = query->sm_ah->ah;
query->mad,
sizeof (struct ib_sa_mad),
DMA_TO_DEVICE);
gather_list.length = sizeof (struct ib_sa_mad);
gather_list.lkey = port->agent->mr->lkey;
pci_unmap_addr_set(query, mapping, gather_list.addr);
ret = ib_post_send_mad(port->agent, &wr, &bad_wr); ret = ib_post_send_mad(query->mad_buf, NULL);
if (ret) { if (ret) {
dma_unmap_single(port->agent->device->dma_device,
pci_unmap_addr(query, mapping),
sizeof (struct ib_sa_mad),
DMA_TO_DEVICE);
kref_put(&query->sm_ah->ref, free_sm_ah);
spin_lock_irqsave(&idr_lock, flags); spin_lock_irqsave(&idr_lock, flags);
idr_remove(&query_idr, query->id); idr_remove(&query_idr, id);
spin_unlock_irqrestore(&idr_lock, flags); spin_unlock_irqrestore(&idr_lock, flags);
kref_put(&query->sm_ah->ref, free_sm_ah);
} }
/* /*
* It's not safe to dereference query any more, because the * It's not safe to dereference query any more, because the
* send may already have completed and freed the query in * send may already have completed and freed the query in
* another context. So use wr.wr_id, which has a copy of the * another context.
* query's id.
*/ */
return ret ? ret : wr.wr_id; return ret ? ret : id;
} }
static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
@ -543,7 +519,6 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_path_rec_release(struct ib_sa_query *sa_query) static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
{ {
kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_path_query, sa_query)); kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
} }
@ -585,6 +560,7 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
struct ib_sa_port *port; struct ib_sa_port *port;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_sa_mad *mad;
int ret; int ret;
if (!sa_dev) if (!sa_dev)
@ -596,37 +572,45 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
query = kmalloc(sizeof *query, gfp_mask); query = kmalloc(sizeof *query, gfp_mask);
if (!query) if (!query)
return -ENOMEM; return -ENOMEM;
query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
if (!query->sa_query.mad) { query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
kfree(query); 0, IB_MGMT_SA_HDR,
return -ENOMEM; IB_MGMT_SA_DATA, gfp_mask);
if (!query->sa_query.mad_buf) {
ret = -ENOMEM;
goto err1;
} }
query->callback = callback; query->callback = callback;
query->context = context; query->context = context;
init_mad(query->sa_query.mad, agent); mad = query->sa_query.mad_buf->mad;
init_mad(mad, agent);
query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL; query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
query->sa_query.release = ib_sa_path_rec_release; query->sa_query.release = ib_sa_path_rec_release;
query->sa_query.port = port; query->sa_query.port = port;
query->sa_query.mad->mad_hdr.method = IB_MGMT_METHOD_GET; mad->mad_hdr.method = IB_MGMT_METHOD_GET;
query->sa_query.mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC); mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);
query->sa_query.mad->sa_hdr.comp_mask = comp_mask; mad->sa_hdr.comp_mask = comp_mask;
ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
rec, query->sa_query.mad->data);
*sa_query = &query->sa_query; *sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms); ret = send_mad(&query->sa_query, timeout_ms);
if (ret < 0) { if (ret < 0)
*sa_query = NULL; goto err2;
kfree(query->sa_query.mad);
kfree(query);
}
return ret; return ret;
err2:
*sa_query = NULL;
ib_free_send_mad(query->sa_query.mad_buf);
err1:
kfree(query);
return ret;
} }
EXPORT_SYMBOL(ib_sa_path_rec_get); EXPORT_SYMBOL(ib_sa_path_rec_get);
@ -649,7 +633,6 @@ static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_service_rec_release(struct ib_sa_query *sa_query) static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
{ {
kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_service_query, sa_query)); kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
} }
@ -693,6 +676,7 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
struct ib_sa_port *port; struct ib_sa_port *port;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_sa_mad *mad;
int ret; int ret;
if (!sa_dev) if (!sa_dev)
@ -709,38 +693,46 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
query = kmalloc(sizeof *query, gfp_mask); query = kmalloc(sizeof *query, gfp_mask);
if (!query) if (!query)
return -ENOMEM; return -ENOMEM;
query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
if (!query->sa_query.mad) { query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
kfree(query); 0, IB_MGMT_SA_HDR,
return -ENOMEM; IB_MGMT_SA_DATA, gfp_mask);
if (!query->sa_query.mad_buf) {
ret = -ENOMEM;
goto err1;
} }
query->callback = callback; query->callback = callback;
query->context = context; query->context = context;
init_mad(query->sa_query.mad, agent); mad = query->sa_query.mad_buf->mad;
init_mad(mad, agent);
query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL; query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
query->sa_query.release = ib_sa_service_rec_release; query->sa_query.release = ib_sa_service_rec_release;
query->sa_query.port = port; query->sa_query.port = port;
query->sa_query.mad->mad_hdr.method = method; mad->mad_hdr.method = method;
query->sa_query.mad->mad_hdr.attr_id = mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
cpu_to_be16(IB_SA_ATTR_SERVICE_REC); mad->sa_hdr.comp_mask = comp_mask;
query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table), ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
rec, query->sa_query.mad->data); rec, mad->data);
*sa_query = &query->sa_query; *sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms); ret = send_mad(&query->sa_query, timeout_ms);
if (ret < 0) { if (ret < 0)
*sa_query = NULL; goto err2;
kfree(query->sa_query.mad);
kfree(query);
}
return ret; return ret;
err2:
*sa_query = NULL;
ib_free_send_mad(query->sa_query.mad_buf);
err1:
kfree(query);
return ret;
} }
EXPORT_SYMBOL(ib_sa_service_rec_query); EXPORT_SYMBOL(ib_sa_service_rec_query);
@ -763,7 +755,6 @@ static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query) static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
{ {
kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query)); kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
} }
@ -782,6 +773,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
struct ib_sa_port *port; struct ib_sa_port *port;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_sa_mad *mad;
int ret; int ret;
if (!sa_dev) if (!sa_dev)
@ -793,53 +785,55 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
query = kmalloc(sizeof *query, gfp_mask); query = kmalloc(sizeof *query, gfp_mask);
if (!query) if (!query)
return -ENOMEM; return -ENOMEM;
query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
if (!query->sa_query.mad) { query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
kfree(query); 0, IB_MGMT_SA_HDR,
return -ENOMEM; IB_MGMT_SA_DATA, gfp_mask);
if (!query->sa_query.mad_buf) {
ret = -ENOMEM;
goto err1;
} }
query->callback = callback; query->callback = callback;
query->context = context; query->context = context;
init_mad(query->sa_query.mad, agent); mad = query->sa_query.mad_buf->mad;
init_mad(mad, agent);
query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL; query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
query->sa_query.release = ib_sa_mcmember_rec_release; query->sa_query.release = ib_sa_mcmember_rec_release;
query->sa_query.port = port; query->sa_query.port = port;
query->sa_query.mad->mad_hdr.method = method; mad->mad_hdr.method = method;
query->sa_query.mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC); mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
query->sa_query.mad->sa_hdr.comp_mask = comp_mask; mad->sa_hdr.comp_mask = comp_mask;
ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table), ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
rec, query->sa_query.mad->data); rec, mad->data);
*sa_query = &query->sa_query; *sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms); ret = send_mad(&query->sa_query, timeout_ms);
if (ret < 0) { if (ret < 0)
*sa_query = NULL; goto err2;
kfree(query->sa_query.mad);
kfree(query);
}
return ret; return ret;
err2:
*sa_query = NULL;
ib_free_send_mad(query->sa_query.mad_buf);
err1:
kfree(query);
return ret;
} }
EXPORT_SYMBOL(ib_sa_mcmember_rec_query); EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
static void send_handler(struct ib_mad_agent *agent, static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc) struct ib_mad_send_wc *mad_send_wc)
{ {
struct ib_sa_query *query; struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&idr_lock, flags);
query = idr_find(&query_idr, mad_send_wc->wr_id);
spin_unlock_irqrestore(&idr_lock, flags);
if (!query)
return;
if (query->callback) if (query->callback)
switch (mad_send_wc->status) { switch (mad_send_wc->status) {
case IB_WC_SUCCESS: case IB_WC_SUCCESS:
@ -856,30 +850,25 @@ static void send_handler(struct ib_mad_agent *agent,
break; break;
} }
dma_unmap_single(agent->device->dma_device,
pci_unmap_addr(query, mapping),
sizeof (struct ib_sa_mad),
DMA_TO_DEVICE);
kref_put(&query->sm_ah->ref, free_sm_ah);
query->release(query);
spin_lock_irqsave(&idr_lock, flags); spin_lock_irqsave(&idr_lock, flags);
idr_remove(&query_idr, mad_send_wc->wr_id); idr_remove(&query_idr, query->id);
spin_unlock_irqrestore(&idr_lock, flags); spin_unlock_irqrestore(&idr_lock, flags);
ib_free_send_mad(mad_send_wc->send_buf);
kref_put(&query->sm_ah->ref, free_sm_ah);
query->release(query);
} }
static void recv_handler(struct ib_mad_agent *mad_agent, static void recv_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_recv_wc *mad_recv_wc) struct ib_mad_recv_wc *mad_recv_wc)
{ {
struct ib_sa_query *query; struct ib_sa_query *query;
unsigned long flags; struct ib_mad_send_buf *mad_buf;
spin_lock_irqsave(&idr_lock, flags); mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
query = idr_find(&query_idr, mad_recv_wc->wc->wr_id); query = mad_buf->context[0];
spin_unlock_irqrestore(&idr_lock, flags);
if (query && query->callback) { if (query->callback) {
if (mad_recv_wc->wc->status == IB_WC_SUCCESS) if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
query->callback(query, query->callback(query,
mad_recv_wc->recv_buf.mad->mad_hdr.status ? mad_recv_wc->recv_buf.mad->mad_hdr.status ?

View File

@ -39,6 +39,8 @@
#ifndef __SMI_H_ #ifndef __SMI_H_
#define __SMI_H_ #define __SMI_H_
#include <rdma/ib_smi.h>
int smi_handle_dr_smp_recv(struct ib_smp *smp, int smi_handle_dr_smp_recv(struct ib_smp *smp,
u8 node_type, u8 node_type,
int port_num, int port_num,

View File

@ -96,7 +96,6 @@ struct ib_umad_file {
}; };
struct ib_umad_packet { struct ib_umad_packet {
struct ib_ah *ah;
struct ib_mad_send_buf *msg; struct ib_mad_send_buf *msg;
struct list_head list; struct list_head list;
int length; int length;
@ -139,10 +138,10 @@ static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *send_wc) struct ib_mad_send_wc *send_wc)
{ {
struct ib_umad_file *file = agent->context; struct ib_umad_file *file = agent->context;
struct ib_umad_packet *timeout, *packet = struct ib_umad_packet *timeout;
(void *) (unsigned long) send_wc->wr_id; struct ib_umad_packet *packet = send_wc->send_buf->context[0];
ib_destroy_ah(packet->msg->send_wr.wr.ud.ah); ib_destroy_ah(packet->msg->ah);
ib_free_send_mad(packet->msg); ib_free_send_mad(packet->msg);
if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) { if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
@ -268,11 +267,11 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
struct ib_umad_packet *packet; struct ib_umad_packet *packet;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_ah_attr ah_attr; struct ib_ah_attr ah_attr;
struct ib_send_wr *bad_wr; struct ib_ah *ah;
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
u8 method; u8 method;
__be64 *tid; __be64 *tid;
int ret, length, hdr_len, data_len, rmpp_hdr_size; int ret, length, hdr_len, rmpp_hdr_size;
int rmpp_active = 0; int rmpp_active = 0;
if (count < sizeof (struct ib_user_mad)) if (count < sizeof (struct ib_user_mad))
@ -321,9 +320,9 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class; ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;
} }
packet->ah = ib_create_ah(agent->qp->pd, &ah_attr); ah = ib_create_ah(agent->qp->pd, &ah_attr);
if (IS_ERR(packet->ah)) { if (IS_ERR(ah)) {
ret = PTR_ERR(packet->ah); ret = PTR_ERR(ah);
goto err_up; goto err_up;
} }
@ -337,12 +336,10 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
/* Validate that the management class can support RMPP */ /* Validate that the management class can support RMPP */
if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
hdr_len = offsetof(struct ib_sa_mad, data); hdr_len = IB_MGMT_SA_HDR;
data_len = length - hdr_len;
} else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
(rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) { (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {
hdr_len = offsetof(struct ib_vendor_mad, data); hdr_len = IB_MGMT_VENDOR_HDR;
data_len = length - hdr_len;
} else { } else {
ret = -EINVAL; ret = -EINVAL;
goto err_ah; goto err_ah;
@ -353,25 +350,23 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
ret = -EINVAL; ret = -EINVAL;
goto err_ah; goto err_ah;
} }
hdr_len = offsetof(struct ib_mad, data); hdr_len = IB_MGMT_MAD_HDR;
data_len = length - hdr_len;
} }
packet->msg = ib_create_send_mad(agent, packet->msg = ib_create_send_mad(agent,
be32_to_cpu(packet->mad.hdr.qpn), be32_to_cpu(packet->mad.hdr.qpn),
0, packet->ah, rmpp_active, 0, rmpp_active,
hdr_len, data_len, hdr_len, length - hdr_len,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(packet->msg)) { if (IS_ERR(packet->msg)) {
ret = PTR_ERR(packet->msg); ret = PTR_ERR(packet->msg);
goto err_ah; goto err_ah;
} }
packet->msg->send_wr.wr.ud.timeout_ms = packet->mad.hdr.timeout_ms; packet->msg->ah = ah;
packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries; packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
packet->msg->retries = packet->mad.hdr.retries;
/* Override send WR WRID initialized in ib_create_send_mad */ packet->msg->context[0] = packet;
packet->msg->send_wr.wr_id = (unsigned long) packet;
if (!rmpp_active) { if (!rmpp_active) {
/* Copy message from user into send buffer */ /* Copy message from user into send buffer */
@ -403,17 +398,17 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
* transaction ID matches the agent being used to send the * transaction ID matches the agent being used to send the
* MAD. * MAD.
*/ */
method = packet->msg->mad->mad_hdr.method; method = ((struct ib_mad_hdr *) packet->msg)->method;
if (!(method & IB_MGMT_METHOD_RESP) && if (!(method & IB_MGMT_METHOD_RESP) &&
method != IB_MGMT_METHOD_TRAP_REPRESS && method != IB_MGMT_METHOD_TRAP_REPRESS &&
method != IB_MGMT_METHOD_SEND) { method != IB_MGMT_METHOD_SEND) {
tid = &packet->msg->mad->mad_hdr.tid; tid = &((struct ib_mad_hdr *) packet->msg)->tid;
*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 | *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
(be64_to_cpup(tid) & 0xffffffff)); (be64_to_cpup(tid) & 0xffffffff));
} }
ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr); ret = ib_post_send_mad(packet->msg, NULL);
if (ret) if (ret)
goto err_msg; goto err_msg;
@ -425,7 +420,7 @@ err_msg:
ib_free_send_mad(packet->msg); ib_free_send_mad(packet->msg);
err_ah: err_ah:
ib_destroy_ah(packet->ah); ib_destroy_ah(ah);
err_up: err_up:
up_read(&file->agent_mutex); up_read(&file->agent_mutex);

View File

@ -46,11 +46,6 @@ enum {
MTHCA_VENDOR_CLASS2 = 0xa MTHCA_VENDOR_CLASS2 = 0xa
}; };
struct mthca_trap_mad {
struct ib_mad *mad;
DECLARE_PCI_UNMAP_ADDR(mapping)
};
static void update_sm_ah(struct mthca_dev *dev, static void update_sm_ah(struct mthca_dev *dev,
u8 port_num, u16 lid, u8 sl) u8 port_num, u16 lid, u8 sl)
{ {
@ -116,49 +111,14 @@ static void forward_trap(struct mthca_dev *dev,
struct ib_mad *mad) struct ib_mad *mad)
{ {
int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
struct mthca_trap_mad *tmad; struct ib_mad_send_buf *send_buf;
struct ib_sge gather_list;
struct ib_send_wr *bad_wr, wr = {
.opcode = IB_WR_SEND,
.sg_list = &gather_list,
.num_sge = 1,
.send_flags = IB_SEND_SIGNALED,
.wr = {
.ud = {
.remote_qpn = qpn,
.remote_qkey = qpn ? IB_QP1_QKEY : 0,
.timeout_ms = 0
}
}
};
struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn]; struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn];
int ret; int ret;
unsigned long flags; unsigned long flags;
if (agent) { if (agent) {
tmad = kmalloc(sizeof *tmad, GFP_KERNEL); send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
if (!tmad) IB_MGMT_MAD_DATA, GFP_ATOMIC);
return;
tmad->mad = kmalloc(sizeof *tmad->mad, GFP_KERNEL);
if (!tmad->mad) {
kfree(tmad);
return;
}
memcpy(tmad->mad, mad, sizeof *mad);
wr.wr.ud.mad_hdr = &tmad->mad->mad_hdr;
wr.wr_id = (unsigned long) tmad;
gather_list.addr = dma_map_single(agent->device->dma_device,
tmad->mad,
sizeof *tmad->mad,
DMA_TO_DEVICE);
gather_list.length = sizeof *tmad->mad;
gather_list.lkey = to_mpd(agent->qp->pd)->ntmr.ibmr.lkey;
pci_unmap_addr_set(tmad, mapping, gather_list.addr);
/* /*
* We rely here on the fact that MLX QPs don't use the * We rely here on the fact that MLX QPs don't use the
* address handle after the send is posted (this is * address handle after the send is posted (this is
@ -166,21 +126,15 @@ static void forward_trap(struct mthca_dev *dev,
* it's OK for our devices). * it's OK for our devices).
*/ */
spin_lock_irqsave(&dev->sm_lock, flags); spin_lock_irqsave(&dev->sm_lock, flags);
wr.wr.ud.ah = dev->sm_ah[port_num - 1]; memcpy(send_buf->mad, mad, sizeof *mad);
if (wr.wr.ud.ah) if ((send_buf->ah = dev->sm_ah[port_num - 1]))
ret = ib_post_send_mad(agent, &wr, &bad_wr); ret = ib_post_send_mad(send_buf, NULL);
else else
ret = -EINVAL; ret = -EINVAL;
spin_unlock_irqrestore(&dev->sm_lock, flags); spin_unlock_irqrestore(&dev->sm_lock, flags);
if (ret) { if (ret)
dma_unmap_single(agent->device->dma_device, ib_free_send_mad(send_buf);
pci_unmap_addr(tmad, mapping),
sizeof *tmad->mad,
DMA_TO_DEVICE);
kfree(tmad->mad);
kfree(tmad);
}
} }
} }
@ -267,15 +221,7 @@ int mthca_process_mad(struct ib_device *ibdev,
static void send_handler(struct ib_mad_agent *agent, static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc) struct ib_mad_send_wc *mad_send_wc)
{ {
struct mthca_trap_mad *tmad = ib_free_send_mad(mad_send_wc->send_buf);
(void *) (unsigned long) mad_send_wc->wr_id;
dma_unmap_single(agent->device->dma_device,
pci_unmap_addr(tmad, mapping),
sizeof *tmad->mad,
DMA_TO_DEVICE);
kfree(tmad->mad);
kfree(tmad);
} }
int mthca_create_agents(struct mthca_dev *dev) int mthca_create_agents(struct mthca_dev *dev)

View File

@ -109,10 +109,14 @@
#define IB_QP_SET_QKEY 0x80000000 #define IB_QP_SET_QKEY 0x80000000
enum { enum {
IB_MGMT_MAD_HDR = 24,
IB_MGMT_MAD_DATA = 232, IB_MGMT_MAD_DATA = 232,
IB_MGMT_RMPP_HDR = 36,
IB_MGMT_RMPP_DATA = 220, IB_MGMT_RMPP_DATA = 220,
IB_MGMT_VENDOR_HDR = 40,
IB_MGMT_VENDOR_DATA = 216, IB_MGMT_VENDOR_DATA = 216,
IB_MGMT_SA_DATA = 200 IB_MGMT_SA_HDR = 56,
IB_MGMT_SA_DATA = 200,
}; };
struct ib_mad_hdr { struct ib_mad_hdr {
@ -203,26 +207,25 @@ struct ib_class_port_info
/** /**
* ib_mad_send_buf - MAD data buffer and work request for sends. * ib_mad_send_buf - MAD data buffer and work request for sends.
* @mad: References an allocated MAD data buffer. The size of the data * @next: A pointer used to chain together MADs for posting.
* buffer is specified in the @send_wr.length field. * @mad: References an allocated MAD data buffer.
* @mapping: DMA mapping information.
* @mad_agent: MAD agent that allocated the buffer. * @mad_agent: MAD agent that allocated the buffer.
* @ah: The address handle to use when sending the MAD.
* @context: User-controlled context fields. * @context: User-controlled context fields.
* @send_wr: An initialized work request structure used when sending the MAD. * @timeout_ms: Time to wait for a response.
* The wr_id field of the work request is initialized to reference this * @retries: Number of times to retry a request for a response.
* data structure.
* @sge: A scatter-gather list referenced by the work request.
* *
* Users are responsible for initializing the MAD buffer itself, with the * Users are responsible for initializing the MAD buffer itself, with the
* exception of specifying the payload length field in any RMPP MAD. * exception of specifying the payload length field in any RMPP MAD.
*/ */
struct ib_mad_send_buf { struct ib_mad_send_buf {
struct ib_mad *mad; struct ib_mad_send_buf *next;
DECLARE_PCI_UNMAP_ADDR(mapping) void *mad;
struct ib_mad_agent *mad_agent; struct ib_mad_agent *mad_agent;
struct ib_ah *ah;
void *context[2]; void *context[2];
struct ib_send_wr send_wr; int timeout_ms;
struct ib_sge sge; int retries;
}; };
/** /**
@ -287,7 +290,7 @@ typedef void (*ib_mad_send_handler)(struct ib_mad_agent *mad_agent,
* or @mad_send_wc. * or @mad_send_wc.
*/ */
typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent, typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent,
struct ib_send_wr *send_wr, struct ib_mad_send_buf *send_buf,
struct ib_mad_send_wc *mad_send_wc); struct ib_mad_send_wc *mad_send_wc);
/** /**
@ -334,13 +337,13 @@ struct ib_mad_agent {
/** /**
* ib_mad_send_wc - MAD send completion information. * ib_mad_send_wc - MAD send completion information.
* @wr_id: Work request identifier associated with the send MAD request. * @send_buf: Send MAD data buffer associated with the send MAD request.
* @status: Completion status. * @status: Completion status.
* @vendor_err: Optional vendor error information returned with a failed * @vendor_err: Optional vendor error information returned with a failed
* request. * request.
*/ */
struct ib_mad_send_wc { struct ib_mad_send_wc {
u64 wr_id; struct ib_mad_send_buf *send_buf;
enum ib_wc_status status; enum ib_wc_status status;
u32 vendor_err; u32 vendor_err;
}; };
@ -366,7 +369,7 @@ struct ib_mad_recv_buf {
* @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers. * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
* @mad_len: The length of the received MAD, without duplicated headers. * @mad_len: The length of the received MAD, without duplicated headers.
* *
* For received response, the wr_id field of the wc is set to the wr_id * For received response, the wr_id contains a pointer to the ib_mad_send_buf
* for the corresponding send request. * for the corresponding send request.
*/ */
struct ib_mad_recv_wc { struct ib_mad_recv_wc {
@ -463,9 +466,9 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
/** /**
* ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
* with the registered client. * with the registered client.
* @mad_agent: Specifies the associated registration to post the send to. * @send_buf: Specifies the information needed to send the MAD(s).
* @send_wr: Specifies the information needed to send the MAD(s). * @bad_send_buf: Specifies the MAD on which an error was encountered. This
* @bad_send_wr: Specifies the MAD on which an error was encountered. * parameter is optional if only a single MAD is posted.
* *
* Sent MADs are not guaranteed to complete in the order that they were posted. * Sent MADs are not guaranteed to complete in the order that they were posted.
* *
@ -479,9 +482,8 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
* defined data being transferred. The paylen_newwin field should be * defined data being transferred. The paylen_newwin field should be
* specified in network-byte order. * specified in network-byte order.
*/ */
int ib_post_send_mad(struct ib_mad_agent *mad_agent, int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
struct ib_send_wr *send_wr, struct ib_mad_send_buf **bad_send_buf);
struct ib_send_wr **bad_send_wr);
/** /**
* ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer. * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer.
@ -507,23 +509,25 @@ void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc);
/** /**
* ib_cancel_mad - Cancels an outstanding send MAD operation. * ib_cancel_mad - Cancels an outstanding send MAD operation.
* @mad_agent: Specifies the registration associated with sent MAD. * @mad_agent: Specifies the registration associated with sent MAD.
* @wr_id: Indicates the work request identifier of the MAD to cancel. * @send_buf: Indicates the MAD to cancel.
* *
* MADs will be returned to the user through the corresponding * MADs will be returned to the user through the corresponding
* ib_mad_send_handler. * ib_mad_send_handler.
*/ */
void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id); void ib_cancel_mad(struct ib_mad_agent *mad_agent,
struct ib_mad_send_buf *send_buf);
/** /**
* ib_modify_mad - Modifies an outstanding send MAD operation. * ib_modify_mad - Modifies an outstanding send MAD operation.
* @mad_agent: Specifies the registration associated with sent MAD. * @mad_agent: Specifies the registration associated with sent MAD.
* @wr_id: Indicates the work request identifier of the MAD to modify. * @send_buf: Indicates the MAD to modify.
* @timeout_ms: New timeout value for sent MAD. * @timeout_ms: New timeout value for sent MAD.
* *
* This call will reset the timeout value for a sent MAD to the specified * This call will reset the timeout value for a sent MAD to the specified
* value. * value.
*/ */
int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms); int ib_modify_mad(struct ib_mad_agent *mad_agent,
struct ib_mad_send_buf *send_buf, u32 timeout_ms);
/** /**
* ib_redirect_mad_qp - Registers a QP for MAD services. * ib_redirect_mad_qp - Registers a QP for MAD services.
@ -572,7 +576,6 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
* @remote_qpn: Specifies the QPN of the receiving node. * @remote_qpn: Specifies the QPN of the receiving node.
* @pkey_index: Specifies which PKey the MAD will be sent using. This field * @pkey_index: Specifies which PKey the MAD will be sent using. This field
* is valid only if the remote_qpn is QP 1. * is valid only if the remote_qpn is QP 1.
* @ah: References the address handle used to transfer to the remote node.
* @rmpp_active: Indicates if the send will enable RMPP. * @rmpp_active: Indicates if the send will enable RMPP.
* @hdr_len: Indicates the size of the data header of the MAD. This length * @hdr_len: Indicates the size of the data header of the MAD. This length
* should include the common MAD header, RMPP header, plus any class * should include the common MAD header, RMPP header, plus any class
@ -582,11 +585,10 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
* additional padding that may be necessary. * additional padding that may be necessary.
* @gfp_mask: GFP mask used for the memory allocation. * @gfp_mask: GFP mask used for the memory allocation.
* *
* This is a helper routine that may be used to allocate a MAD. Users are * This routine allocates a MAD for sending. The returned MAD send buffer
* not required to allocate outbound MADs using this call. The returned * will reference a data buffer usable for sending a MAD, along
* MAD send buffer will reference a data buffer usable for sending a MAD, along
* with an initialized work request structure. Users may modify the returned * with an initialized work request structure. Users may modify the returned
* MAD data buffer or work request before posting the send. * MAD data buffer before posting the send.
* *
* The returned data buffer will be cleared. Users are responsible for * The returned data buffer will be cleared. Users are responsible for
* initializing the common MAD and any class specific headers. If @rmpp_active * initializing the common MAD and any class specific headers. If @rmpp_active
@ -594,7 +596,7 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
*/ */
struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
u32 remote_qpn, u16 pkey_index, u32 remote_qpn, u16 pkey_index,
struct ib_ah *ah, int rmpp_active, int rmpp_active,
int hdr_len, int data_len, int hdr_len, int data_len,
gfp_t gfp_mask); gfp_t gfp_mask);

View File

@ -595,11 +595,8 @@ struct ib_send_wr {
} atomic; } atomic;
struct { struct {
struct ib_ah *ah; struct ib_ah *ah;
struct ib_mad_hdr *mad_hdr;
u32 remote_qpn; u32 remote_qpn;
u32 remote_qkey; u32 remote_qkey;
int timeout_ms; /* valid for MADs only */
int retries; /* valid for MADs only */
u16 pkey_index; /* valid for GSI only */ u16 pkey_index; /* valid for GSI only */
u8 port_num; /* valid for DR SMPs on switch only */ u8 port_num; /* valid for DR SMPs on switch only */
} ud; } ud;