* $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
*/
#include <linux/dma-mapping.h>
-#include <rdma/ib_cache.h>
#include "mad_priv.h"
#include "mad_rmpp.h"
MODULE_AUTHOR("Hal Rosenstock");
MODULE_AUTHOR("Sean Hefty");
-static kmem_cache_t *ib_mad_cache;
+
+kmem_cache_t *ib_mad_cache;
static struct list_head ib_mad_port_list;
static u32 ib_mad_client_id = 0;
return 0;
}
-int ib_response_mad(struct ib_mad *mad)
-{
- return ((mad->mad_hdr.method & IB_MGMT_METHOD_RESP) ||
- (mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) ||
- ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_BM) &&
- (mad->mad_hdr.attr_mod & IB_BM_ATTR_MOD_RESP)));
-}
-EXPORT_SYMBOL(ib_response_mad);
-
/*
* ib_register_mad_agent - Register to send/receive MADs
*/
}
EXPORT_SYMBOL(ib_unregister_mad_agent);
+static inline int response_mad(struct ib_mad *mad)
+{
+ /* Trap represses are responses although response bit is reset */
+ return ((mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) ||
+ (mad->mad_hdr.method & IB_MGMT_METHOD_RESP));
+}
+
static void dequeue_mad(struct ib_mad_list_head *mad_list)
{
struct ib_mad_queue *mad_queue;
switch (ret)
{
case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY:
- if (ib_response_mad(&mad_priv->mad.mad) &&
+ if (response_mad(&mad_priv->mad.mad) &&
mad_agent_priv->agent.recv_handler) {
local->mad_priv = mad_priv;
local->recv_mad_agent = mad_agent_priv;
unsigned long flags;
spin_lock_irqsave(&port_priv->reg_lock, flags);
- if (ib_response_mad(mad)) {
+ if (response_mad(mad)) {
u32 hi_tid;
struct ib_mad_agent_private *entry;
rwc->recv_buf.mad->mad_hdr.mgmt_class;
}
-static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
- struct ib_mad_send_wr_private *wr,
+static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
struct ib_mad_recv_wc *rwc )
{
struct ib_ah_attr attr;
u8 send_resp, rcv_resp;
- union ib_gid sgid;
- struct ib_device *device = mad_agent_priv->agent.device;
- u8 port_num = mad_agent_priv->agent.port_num;
- u8 lmc;
send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
mad_hdr.method & IB_MGMT_METHOD_RESP;
rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
+ if (!send_resp && rcv_resp)
+ /* is request/response. GID/LIDs are both local (same). */
+ return 1;
+
if (send_resp == rcv_resp)
/* both requests, or both responses. GIDs different */
return 0;
/* Assume not equal, to avoid false positives. */
return 0;
- if (!!(attr.ah_flags & IB_AH_GRH) !=
- !!(rwc->wc->wc_flags & IB_WC_GRH))
- /* one has GID, other does not. Assume different */
- return 0;
-
- if (!send_resp && rcv_resp) {
- /* is request/response. */
- if (!(attr.ah_flags & IB_AH_GRH)) {
- if (ib_get_cached_lmc(device, port_num, &lmc))
- return 0;
- return (!lmc || !((attr.src_path_bits ^
- rwc->wc->dlid_path_bits) &
- ((1 << lmc) - 1)));
- } else {
- if (ib_get_cached_gid(device, port_num,
- attr.grh.sgid_index, &sgid))
- return 0;
- return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
- 16);
- }
- }
-
- if (!(attr.ah_flags & IB_AH_GRH))
+ if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH))
return attr.dlid == rwc->wc->slid;
+ else if ((attr.ah_flags & IB_AH_GRH) &&
+ (rwc->wc->wc_flags & IB_WC_GRH))
+ return memcmp(attr.grh.dgid.raw,
+ rwc->recv_buf.grh->sgid.raw, 16) == 0;
else
- return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw,
- 16);
-}
-
-static inline int is_direct(u8 class)
-{
- return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE);
+ /* one has GID, other does not. Assume different */
+ return 0;
}
-
struct ib_mad_send_wr_private*
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
- struct ib_mad_recv_wc *wc)
+ struct ib_mad_recv_wc *mad_recv_wc)
{
- struct ib_mad_send_wr_private *wr;
+ struct ib_mad_send_wr_private *mad_send_wr;
struct ib_mad *mad;
- mad = (struct ib_mad *)wc->recv_buf.mad;
+ mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad;
- list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) {
- if ((wr->tid == mad->mad_hdr.tid) &&
- rcv_has_same_class(wr, wc) &&
- /*
- * Don't check GID for direct routed MADs.
- * These might have permissive LIDs.
- */
- (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
- rcv_has_same_gid(mad_agent_priv, wr, wc)))
- return wr;
+ list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
+ agent_list) {
+ if ((mad_send_wr->tid == mad->mad_hdr.tid) &&
+ rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+ rcv_has_same_gid(mad_send_wr, mad_recv_wc))
+ return mad_send_wr;
}
/*
* It's possible to receive the response before we've
* been notified that the send has completed
*/
- list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) {
- if (is_data_mad(mad_agent_priv, wr->send_buf.mad) &&
- wr->tid == mad->mad_hdr.tid &&
- wr->timeout &&
- rcv_has_same_class(wr, wc) &&
- /*
- * Don't check GID for direct routed MADs.
- * These might have permissive LIDs.
- */
- (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
- rcv_has_same_gid(mad_agent_priv, wr, wc)))
+ list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
+ agent_list) {
+ if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
+ mad_send_wr->tid == mad->mad_hdr.tid &&
+ mad_send_wr->timeout &&
+ rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+ rcv_has_same_gid(mad_send_wr, mad_recv_wc)) {
/* Verify request has not been canceled */
- return (wr->status == IB_WC_SUCCESS) ? wr : NULL;
+ return (mad_send_wr->status == IB_WC_SUCCESS) ?
+ mad_send_wr : NULL;
+ }
}
return NULL;
}
void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
{
mad_send_wr->timeout = 0;
- if (mad_send_wr->refcount == 1)
- list_move_tail(&mad_send_wr->agent_list,
+ if (mad_send_wr->refcount == 1) {
+ list_del(&mad_send_wr->agent_list);
+ list_add_tail(&mad_send_wr->agent_list,
&mad_send_wr->mad_agent_priv->done_list);
+ }
}
static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
}
/* Complete corresponding request */
- if (ib_response_mad(mad_recv_wc->recv_buf.mad)) {
+ if (response_mad(mad_recv_wc->recv_buf.mad)) {
spin_lock_irqsave(&mad_agent_priv->lock, flags);
mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
if (!mad_send_wr) {
queued_send_wr = container_of(mad_list,
struct ib_mad_send_wr_private,
mad_list);
- list_move_tail(&mad_list->list, &send_queue->list);
+ list_del(&mad_list->list);
+ list_add_tail(&mad_list->list, &send_queue->list);
}
spin_unlock_irqrestore(&send_queue->lock, flags);