aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/mad.c94
1 files changed, 63 insertions, 31 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 92c7362f588..b38e02a5db3 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -34,6 +34,7 @@
34 * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ 34 * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
35 */ 35 */
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <rdma/ib_cache.h>
37 38
38#include "mad_priv.h" 39#include "mad_priv.h"
39#include "mad_rmpp.h" 40#include "mad_rmpp.h"
@@ -1672,20 +1673,21 @@ static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr,
1672 rwc->recv_buf.mad->mad_hdr.mgmt_class; 1673 rwc->recv_buf.mad->mad_hdr.mgmt_class;
1673} 1674}
1674 1675
1675static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, 1676static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
1677 struct ib_mad_send_wr_private *wr,
1676 struct ib_mad_recv_wc *rwc ) 1678 struct ib_mad_recv_wc *rwc )
1677{ 1679{
1678 struct ib_ah_attr attr; 1680 struct ib_ah_attr attr;
1679 u8 send_resp, rcv_resp; 1681 u8 send_resp, rcv_resp;
1682 union ib_gid sgid;
1683 struct ib_device *device = mad_agent_priv->agent.device;
1684 u8 port_num = mad_agent_priv->agent.port_num;
1685 u8 lmc;
1680 1686
1681 send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> 1687 send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
1682 mad_hdr.method & IB_MGMT_METHOD_RESP; 1688 mad_hdr.method & IB_MGMT_METHOD_RESP;
1683 rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; 1689 rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
1684 1690
1685 if (!send_resp && rcv_resp)
1686 /* is request/response. GID/LIDs are both local (same). */
1687 return 1;
1688
1689 if (send_resp == rcv_resp) 1691 if (send_resp == rcv_resp)
1690 /* both requests, or both responses. GIDs different */ 1692 /* both requests, or both responses. GIDs different */
1691 return 0; 1693 return 0;
@@ -1694,48 +1696,78 @@ static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
1694 /* Assume not equal, to avoid false positives. */ 1696 /* Assume not equal, to avoid false positives. */
1695 return 0; 1697 return 0;
1696 1698
1697 if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) 1699 if (!!(attr.ah_flags & IB_AH_GRH) !=
1698 return attr.dlid == rwc->wc->slid; 1700 !!(rwc->wc->wc_flags & IB_WC_GRH))
1699 else if ((attr.ah_flags & IB_AH_GRH) &&
1700 (rwc->wc->wc_flags & IB_WC_GRH))
1701 return memcmp(attr.grh.dgid.raw,
1702 rwc->recv_buf.grh->sgid.raw, 16) == 0;
1703 else
1704 /* one has GID, other does not. Assume different */ 1701 /* one has GID, other does not. Assume different */
1705 return 0; 1702 return 0;
1703
1704 if (!send_resp && rcv_resp) {
1705 /* is request/response. */
1706 if (!(attr.ah_flags & IB_AH_GRH)) {
1707 if (ib_get_cached_lmc(device, port_num, &lmc))
1708 return 0;
1709 return (!lmc || !((attr.src_path_bits ^
1710 rwc->wc->dlid_path_bits) &
1711 ((1 << lmc) - 1)));
1712 } else {
1713 if (ib_get_cached_gid(device, port_num,
1714 attr.grh.sgid_index, &sgid))
1715 return 0;
1716 return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
1717 16);
1718 }
1719 }
1720
1721 if (!(attr.ah_flags & IB_AH_GRH))
1722 return attr.dlid == rwc->wc->slid;
1723 else
1724 return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw,
1725 16);
1706} 1726}
1727
1728static inline int is_direct(u8 class)
1729{
1730 return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE);
1731}
1732
1707struct ib_mad_send_wr_private* 1733struct ib_mad_send_wr_private*
1708ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, 1734ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
1709 struct ib_mad_recv_wc *mad_recv_wc) 1735 struct ib_mad_recv_wc *wc)
1710{ 1736{
1711 struct ib_mad_send_wr_private *mad_send_wr; 1737 struct ib_mad_send_wr_private *wr;
1712 struct ib_mad *mad; 1738 struct ib_mad *mad;
1713 1739
1714 mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; 1740 mad = (struct ib_mad *)wc->recv_buf.mad;
1715 1741
1716 list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, 1742 list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) {
1717 agent_list) { 1743 if ((wr->tid == mad->mad_hdr.tid) &&
1718 if ((mad_send_wr->tid == mad->mad_hdr.tid) && 1744 rcv_has_same_class(wr, wc) &&
1719 rcv_has_same_class(mad_send_wr, mad_recv_wc) && 1745 /*
1720 rcv_has_same_gid(mad_send_wr, mad_recv_wc)) 1746 * Don't check GID for direct routed MADs.
1721 return mad_send_wr; 1747 * These might have permissive LIDs.
1748 */
1749 (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
1750 rcv_has_same_gid(mad_agent_priv, wr, wc)))
1751 return wr;
1722 } 1752 }
1723 1753
1724 /* 1754 /*
1725 * It's possible to receive the response before we've 1755 * It's possible to receive the response before we've
1726 * been notified that the send has completed 1756 * been notified that the send has completed
1727 */ 1757 */
1728 list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, 1758 list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) {
1729 agent_list) { 1759 if (is_data_mad(mad_agent_priv, wr->send_buf.mad) &&
1730 if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && 1760 wr->tid == mad->mad_hdr.tid &&
1731 mad_send_wr->tid == mad->mad_hdr.tid && 1761 wr->timeout &&
1732 mad_send_wr->timeout && 1762 rcv_has_same_class(wr, wc) &&
1733 rcv_has_same_class(mad_send_wr, mad_recv_wc) && 1763 /*
1734 rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { 1764 * Don't check GID for direct routed MADs.
1765 * These might have permissive LIDs.
1766 */
1767 (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
1768 rcv_has_same_gid(mad_agent_priv, wr, wc)))
1735 /* Verify request has not been canceled */ 1769 /* Verify request has not been canceled */
1736 return (mad_send_wr->status == IB_WC_SUCCESS) ? 1770 return (wr->status == IB_WC_SUCCESS) ? wr : NULL;
1737 mad_send_wr : NULL;
1738 }
1739 } 1771 }
1740 return NULL; 1772 return NULL;
1741} 1773}