diff options
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r-- | drivers/infiniband/core/mad.c | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 92c7362f5887..b38e02a5db35 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 | ||
1675 | static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, | 1676 | static 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 | |||
1728 | static inline int is_direct(u8 class) | ||
1729 | { | ||
1730 | return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE); | ||
1731 | } | ||
1732 | |||
1707 | struct ib_mad_send_wr_private* | 1733 | struct ib_mad_send_wr_private* |
1708 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, | 1734 | ib_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 | } |