diff options
| -rw-r--r-- | drivers/infiniband/core/mad.c | 58 | ||||
| -rw-r--r-- | drivers/infiniband/core/mad_priv.h | 3 | ||||
| -rw-r--r-- | drivers/infiniband/core/mad_rmpp.c | 35 |
3 files changed, 67 insertions, 29 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index f7854b65fd55..d4d07012a5ca 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
| @@ -1618,14 +1618,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1618 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); | 1618 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); |
| 1619 | } | 1619 | } |
| 1620 | 1620 | ||
| 1621 | static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, | ||
| 1622 | struct ib_mad_recv_wc *rwc) | ||
| 1623 | { | ||
| 1624 | return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == | ||
| 1625 | rwc->recv_buf.mad->mad_hdr.mgmt_class; | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, | ||
| 1629 | struct ib_mad_recv_wc *rwc ) | ||
| 1630 | { | ||
| 1631 | struct ib_ah_attr attr; | ||
| 1632 | u8 send_resp, rcv_resp; | ||
| 1633 | |||
| 1634 | send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> | ||
| 1635 | mad_hdr.method & IB_MGMT_METHOD_RESP; | ||
| 1636 | rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; | ||
| 1637 | |||
| 1638 | if (!send_resp && rcv_resp) | ||
| 1639 | /* is request/response. GID/LIDs are both local (same). */ | ||
| 1640 | return 1; | ||
| 1641 | |||
| 1642 | if (send_resp == rcv_resp) | ||
| 1643 | /* both requests, or both responses. GIDs different */ | ||
| 1644 | return 0; | ||
| 1645 | |||
| 1646 | if (ib_query_ah(wr->send_buf.ah, &attr)) | ||
| 1647 | /* Assume not equal, to avoid false positives. */ | ||
| 1648 | return 0; | ||
| 1649 | |||
| 1650 | if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) | ||
| 1651 | return attr.dlid == rwc->wc->slid; | ||
| 1652 | else if ((attr.ah_flags & IB_AH_GRH) && | ||
| 1653 | (rwc->wc->wc_flags & IB_WC_GRH)) | ||
| 1654 | return memcmp(attr.grh.dgid.raw, | ||
| 1655 | rwc->recv_buf.grh->sgid.raw, 16) == 0; | ||
| 1656 | else | ||
| 1657 | /* one has GID, other does not. Assume different */ | ||
| 1658 | return 0; | ||
| 1659 | } | ||
| 1621 | struct ib_mad_send_wr_private* | 1660 | struct ib_mad_send_wr_private* |
| 1622 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) | 1661 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, |
| 1662 | struct ib_mad_recv_wc *mad_recv_wc) | ||
| 1623 | { | 1663 | { |
| 1624 | struct ib_mad_send_wr_private *mad_send_wr; | 1664 | struct ib_mad_send_wr_private *mad_send_wr; |
| 1665 | struct ib_mad *mad; | ||
| 1666 | |||
| 1667 | mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; | ||
| 1625 | 1668 | ||
| 1626 | list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, | 1669 | list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, |
| 1627 | agent_list) { | 1670 | agent_list) { |
| 1628 | if (mad_send_wr->tid == tid) | 1671 | if ((mad_send_wr->tid == mad->mad_hdr.tid) && |
| 1672 | rcv_has_same_class(mad_send_wr, mad_recv_wc) && | ||
| 1673 | rcv_has_same_gid(mad_send_wr, mad_recv_wc)) | ||
| 1629 | return mad_send_wr; | 1674 | return mad_send_wr; |
| 1630 | } | 1675 | } |
| 1631 | 1676 | ||
| @@ -1636,7 +1681,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) | |||
| 1636 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, | 1681 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, |
| 1637 | agent_list) { | 1682 | agent_list) { |
| 1638 | if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && | 1683 | if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && |
| 1639 | mad_send_wr->tid == tid && mad_send_wr->timeout) { | 1684 | mad_send_wr->tid == mad->mad_hdr.tid && |
| 1685 | mad_send_wr->timeout && | ||
| 1686 | rcv_has_same_class(mad_send_wr, mad_recv_wc) && | ||
| 1687 | rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { | ||
| 1640 | /* Verify request has not been canceled */ | 1688 | /* Verify request has not been canceled */ |
| 1641 | return (mad_send_wr->status == IB_WC_SUCCESS) ? | 1689 | return (mad_send_wr->status == IB_WC_SUCCESS) ? |
| 1642 | mad_send_wr : NULL; | 1690 | mad_send_wr : NULL; |
| @@ -1661,7 +1709,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1661 | struct ib_mad_send_wr_private *mad_send_wr; | 1709 | struct ib_mad_send_wr_private *mad_send_wr; |
| 1662 | struct ib_mad_send_wc mad_send_wc; | 1710 | struct ib_mad_send_wc mad_send_wc; |
| 1663 | unsigned long flags; | 1711 | unsigned long flags; |
| 1664 | __be64 tid; | ||
| 1665 | 1712 | ||
| 1666 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); | 1713 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); |
| 1667 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); | 1714 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); |
| @@ -1677,9 +1724,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1677 | 1724 | ||
| 1678 | /* Complete corresponding request */ | 1725 | /* Complete corresponding request */ |
| 1679 | if (response_mad(mad_recv_wc->recv_buf.mad)) { | 1726 | if (response_mad(mad_recv_wc->recv_buf.mad)) { |
| 1680 | tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid; | ||
| 1681 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 1727 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
| 1682 | mad_send_wr = ib_find_send_mad(mad_agent_priv, tid); | 1728 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); |
| 1683 | if (!mad_send_wr) { | 1729 | if (!mad_send_wr) { |
| 1684 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1730 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
| 1685 | ib_free_recv_mad(mad_recv_wc); | 1731 | ib_free_recv_mad(mad_recv_wc); |
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index a7125d4b5ccf..6c9c133d71ef 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h | |||
| @@ -216,7 +216,8 @@ extern kmem_cache_t *ib_mad_cache; | |||
| 216 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); | 216 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); |
| 217 | 217 | ||
| 218 | struct ib_mad_send_wr_private * | 218 | struct ib_mad_send_wr_private * |
| 219 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid); | 219 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, |
| 220 | struct ib_mad_recv_wc *mad_recv_wc); | ||
| 220 | 221 | ||
| 221 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, | 222 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, |
| 222 | struct ib_mad_send_wc *mad_send_wc); | 223 | struct ib_mad_send_wc *mad_send_wc); |
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index bacfdd5bddad..a6405079c285 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c | |||
| @@ -562,15 +562,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
| 562 | return ib_send_mad(mad_send_wr); | 562 | return ib_send_mad(mad_send_wr); |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, | 565 | static void abort_send(struct ib_mad_agent_private *agent, |
| 566 | u8 rmpp_status) | 566 | struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status) |
| 567 | { | 567 | { |
| 568 | struct ib_mad_send_wr_private *mad_send_wr; | 568 | struct ib_mad_send_wr_private *mad_send_wr; |
| 569 | struct ib_mad_send_wc wc; | 569 | struct ib_mad_send_wc wc; |
| 570 | unsigned long flags; | 570 | unsigned long flags; |
| 571 | 571 | ||
| 572 | spin_lock_irqsave(&agent->lock, flags); | 572 | spin_lock_irqsave(&agent->lock, flags); |
| 573 | mad_send_wr = ib_find_send_mad(agent, tid); | 573 | mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); |
| 574 | if (!mad_send_wr) | 574 | if (!mad_send_wr) |
| 575 | goto out; /* Unmatched send */ | 575 | goto out; /* Unmatched send */ |
| 576 | 576 | ||
| @@ -612,8 +612,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
| 612 | 612 | ||
| 613 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; | 613 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; |
| 614 | if (rmpp_mad->rmpp_hdr.rmpp_status) { | 614 | if (rmpp_mad->rmpp_hdr.rmpp_status) { |
| 615 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 615 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 616 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
| 617 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 616 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 618 | return; | 617 | return; |
| 619 | } | 618 | } |
| @@ -621,14 +620,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
| 621 | seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); | 620 | seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); |
| 622 | newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | 621 | newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); |
| 623 | if (newwin < seg_num) { | 622 | if (newwin < seg_num) { |
| 624 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 623 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); |
| 625 | IB_MGMT_RMPP_STATUS_W2S); | ||
| 626 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); | 624 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); |
| 627 | return; | 625 | return; |
| 628 | } | 626 | } |
| 629 | 627 | ||
| 630 | spin_lock_irqsave(&agent->lock, flags); | 628 | spin_lock_irqsave(&agent->lock, flags); |
| 631 | mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid); | 629 | mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); |
| 632 | if (!mad_send_wr) | 630 | if (!mad_send_wr) |
| 633 | goto out; /* Unmatched ACK */ | 631 | goto out; /* Unmatched ACK */ |
| 634 | 632 | ||
| @@ -639,8 +637,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
| 639 | if (seg_num > mad_send_wr->send_buf.seg_count || | 637 | if (seg_num > mad_send_wr->send_buf.seg_count || |
| 640 | seg_num > mad_send_wr->newwin) { | 638 | seg_num > mad_send_wr->newwin) { |
| 641 | spin_unlock_irqrestore(&agent->lock, flags); | 639 | spin_unlock_irqrestore(&agent->lock, flags); |
| 642 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 640 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); |
| 643 | IB_MGMT_RMPP_STATUS_S2B); | ||
| 644 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); | 641 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); |
| 645 | return; | 642 | return; |
| 646 | } | 643 | } |
| @@ -728,12 +725,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent, | |||
| 728 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; | 725 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; |
| 729 | 726 | ||
| 730 | if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { | 727 | if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { |
| 731 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 728 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 732 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
| 733 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 729 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 734 | } else | 730 | } else |
| 735 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 731 | abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); |
| 736 | rmpp_mad->rmpp_hdr.rmpp_status); | ||
| 737 | } | 732 | } |
| 738 | 733 | ||
| 739 | static void process_rmpp_abort(struct ib_mad_agent_private *agent, | 734 | static void process_rmpp_abort(struct ib_mad_agent_private *agent, |
| @@ -745,12 +740,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent, | |||
| 745 | 740 | ||
| 746 | if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || | 741 | if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || |
| 747 | rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { | 742 | rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { |
| 748 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 743 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 749 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
| 750 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 744 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
| 751 | } else | 745 | } else |
| 752 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 746 | abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); |
| 753 | rmpp_mad->rmpp_hdr.rmpp_status); | ||
| 754 | } | 747 | } |
| 755 | 748 | ||
| 756 | struct ib_mad_recv_wc * | 749 | struct ib_mad_recv_wc * |
| @@ -764,8 +757,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, | |||
| 764 | return mad_recv_wc; | 757 | return mad_recv_wc; |
| 765 | 758 | ||
| 766 | if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { | 759 | if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { |
| 767 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 760 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); |
| 768 | IB_MGMT_RMPP_STATUS_UNV); | ||
| 769 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); | 761 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); |
| 770 | goto out; | 762 | goto out; |
| 771 | } | 763 | } |
| @@ -783,8 +775,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, | |||
| 783 | process_rmpp_abort(agent, mad_recv_wc); | 775 | process_rmpp_abort(agent, mad_recv_wc); |
| 784 | break; | 776 | break; |
| 785 | default: | 777 | default: |
| 786 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 778 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); |
| 787 | IB_MGMT_RMPP_STATUS_BADT); | ||
| 788 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); | 779 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); |
| 789 | break; | 780 | break; |
| 790 | } | 781 | } |
