aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/mad_rmpp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/mad_rmpp.c')
-rw-r--r--drivers/infiniband/core/mad_rmpp.c148
1 files changed, 48 insertions, 100 deletions
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index 3249e1d8c07b..bacfdd5bddad 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -111,14 +111,14 @@ static int data_offset(u8 mgmt_class)
111 return IB_MGMT_RMPP_HDR; 111 return IB_MGMT_RMPP_HDR;
112} 112}
113 113
114static void format_ack(struct ib_rmpp_mad *ack, 114static void format_ack(struct ib_mad_send_buf *msg,
115 struct ib_rmpp_mad *data, 115 struct ib_rmpp_mad *data,
116 struct mad_rmpp_recv *rmpp_recv) 116 struct mad_rmpp_recv *rmpp_recv)
117{ 117{
118 struct ib_rmpp_mad *ack = msg->mad;
118 unsigned long flags; 119 unsigned long flags;
119 120
120 memcpy(&ack->mad_hdr, &data->mad_hdr, 121 memcpy(ack, &data->mad_hdr, msg->hdr_len);
121 data_offset(data->mad_hdr.mgmt_class));
122 122
123 ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP; 123 ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
124 ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK; 124 ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
@@ -135,16 +135,16 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
135 struct ib_mad_recv_wc *recv_wc) 135 struct ib_mad_recv_wc *recv_wc)
136{ 136{
137 struct ib_mad_send_buf *msg; 137 struct ib_mad_send_buf *msg;
138 int ret; 138 int ret, hdr_len;
139 139
140 hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
140 msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, 141 msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
141 recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR, 142 recv_wc->wc->pkey_index, 1, hdr_len,
142 IB_MGMT_RMPP_DATA, GFP_KERNEL); 143 0, GFP_KERNEL);
143 if (!msg) 144 if (!msg)
144 return; 145 return;
145 146
146 format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, 147 format_ack(msg, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
147 rmpp_recv);
148 msg->ah = rmpp_recv->ah; 148 msg->ah = rmpp_recv->ah;
149 ret = ib_post_send_mad(msg, NULL); 149 ret = ib_post_send_mad(msg, NULL);
150 if (ret) 150 if (ret)
@@ -156,16 +156,17 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
156{ 156{
157 struct ib_mad_send_buf *msg; 157 struct ib_mad_send_buf *msg;
158 struct ib_ah *ah; 158 struct ib_ah *ah;
159 int hdr_len;
159 160
160 ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc, 161 ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
161 recv_wc->recv_buf.grh, agent->port_num); 162 recv_wc->recv_buf.grh, agent->port_num);
162 if (IS_ERR(ah)) 163 if (IS_ERR(ah))
163 return (void *) ah; 164 return (void *) ah;
164 165
166 hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
165 msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, 167 msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
166 recv_wc->wc->pkey_index, 1, 168 recv_wc->wc->pkey_index, 1,
167 IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA, 169 hdr_len, 0, GFP_KERNEL);
168 GFP_KERNEL);
169 if (IS_ERR(msg)) 170 if (IS_ERR(msg))
170 ib_destroy_ah(ah); 171 ib_destroy_ah(ah);
171 else 172 else
@@ -195,8 +196,7 @@ static void nack_recv(struct ib_mad_agent_private *agent,
195 return; 196 return;
196 197
197 rmpp_mad = msg->mad; 198 rmpp_mad = msg->mad;
198 memcpy(rmpp_mad, recv_wc->recv_buf.mad, 199 memcpy(rmpp_mad, recv_wc->recv_buf.mad, msg->hdr_len);
199 data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
200 200
201 rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP; 201 rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
202 rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION; 202 rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION;
@@ -433,44 +433,6 @@ static struct ib_mad_recv_wc * complete_rmpp(struct mad_rmpp_recv *rmpp_recv)
433 return rmpp_wc; 433 return rmpp_wc;
434} 434}
435 435
436void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf)
437{
438 struct ib_mad_recv_buf *seg_buf;
439 struct ib_rmpp_mad *rmpp_mad;
440 void *data;
441 int size, len, offset;
442 u8 flags;
443
444 len = mad_recv_wc->mad_len;
445 if (len <= sizeof(struct ib_mad)) {
446 memcpy(buf, mad_recv_wc->recv_buf.mad, len);
447 return;
448 }
449
450 offset = data_offset(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
451
452 list_for_each_entry(seg_buf, &mad_recv_wc->rmpp_list, list) {
453 rmpp_mad = (struct ib_rmpp_mad *)seg_buf->mad;
454 flags = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr);
455
456 if (flags & IB_MGMT_RMPP_FLAG_FIRST) {
457 data = rmpp_mad;
458 size = sizeof(*rmpp_mad);
459 } else {
460 data = (void *) rmpp_mad + offset;
461 if (flags & IB_MGMT_RMPP_FLAG_LAST)
462 size = len;
463 else
464 size = sizeof(*rmpp_mad) - offset;
465 }
466
467 memcpy(buf, data, size);
468 len -= size;
469 buf += size;
470 }
471}
472EXPORT_SYMBOL(ib_coalesce_recv_mad);
473
474static struct ib_mad_recv_wc * 436static struct ib_mad_recv_wc *
475continue_rmpp(struct ib_mad_agent_private *agent, 437continue_rmpp(struct ib_mad_agent_private *agent,
476 struct ib_mad_recv_wc *mad_recv_wc) 438 struct ib_mad_recv_wc *mad_recv_wc)
@@ -570,50 +532,33 @@ start_rmpp(struct ib_mad_agent_private *agent,
570 return mad_recv_wc; 532 return mad_recv_wc;
571} 533}
572 534
573static inline u64 get_seg_addr(struct ib_mad_send_wr_private *mad_send_wr)
574{
575 return mad_send_wr->sg_list[0].addr + mad_send_wr->data_offset +
576 (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset) *
577 (mad_send_wr->seg_num - 1);
578}
579
580static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) 535static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
581{ 536{
582 struct ib_rmpp_mad *rmpp_mad; 537 struct ib_rmpp_mad *rmpp_mad;
583 int timeout; 538 int timeout;
584 u32 paylen; 539 u32 paylen = 0;
585 540
586 rmpp_mad = mad_send_wr->send_buf.mad; 541 rmpp_mad = mad_send_wr->send_buf.mad;
587 ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); 542 ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
588 rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num); 543 rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(++mad_send_wr->seg_num);
589 544
590 if (mad_send_wr->seg_num == 1) { 545 if (mad_send_wr->seg_num == 1) {
591 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; 546 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST;
592 paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA - 547 paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA -
593 mad_send_wr->pad; 548 mad_send_wr->pad;
594 rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
595 mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
596 } else {
597 mad_send_wr->send_wr.num_sge = 2;
598 mad_send_wr->sg_list[0].length = mad_send_wr->data_offset;
599 mad_send_wr->sg_list[1].addr = get_seg_addr(mad_send_wr);
600 mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
601 mad_send_wr->data_offset;
602 mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
603 rmpp_mad->rmpp_hdr.paylen_newwin = 0;
604 } 549 }
605 550
606 if (mad_send_wr->seg_num == mad_send_wr->total_seg) { 551 if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) {
607 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; 552 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST;
608 paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; 553 paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad;
609 rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
610 } 554 }
555 rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
611 556
612 /* 2 seconds for an ACK until we can find the packet lifetime */ 557 /* 2 seconds for an ACK until we can find the packet lifetime */
613 timeout = mad_send_wr->send_buf.timeout_ms; 558 timeout = mad_send_wr->send_buf.timeout_ms;
614 if (!timeout || timeout > 2000) 559 if (!timeout || timeout > 2000)
615 mad_send_wr->timeout = msecs_to_jiffies(2000); 560 mad_send_wr->timeout = msecs_to_jiffies(2000);
616 mad_send_wr->seg_num++; 561
617 return ib_send_mad(mad_send_wr); 562 return ib_send_mad(mad_send_wr);
618} 563}
619 564
@@ -629,7 +574,7 @@ static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
629 if (!mad_send_wr) 574 if (!mad_send_wr)
630 goto out; /* Unmatched send */ 575 goto out; /* Unmatched send */
631 576
632 if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || 577 if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) ||
633 (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) 578 (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
634 goto out; /* Send is already done */ 579 goto out; /* Send is already done */
635 580
@@ -645,6 +590,18 @@ out:
645 spin_unlock_irqrestore(&agent->lock, flags); 590 spin_unlock_irqrestore(&agent->lock, flags);
646} 591}
647 592
593static inline void adjust_last_ack(struct ib_mad_send_wr_private *wr,
594 int seg_num)
595{
596 struct list_head *list;
597
598 wr->last_ack = seg_num;
599 list = &wr->last_ack_seg->list;
600 list_for_each_entry(wr->last_ack_seg, list, list)
601 if (wr->last_ack_seg->num == seg_num)
602 break;
603}
604
648static void process_rmpp_ack(struct ib_mad_agent_private *agent, 605static void process_rmpp_ack(struct ib_mad_agent_private *agent,
649 struct ib_mad_recv_wc *mad_recv_wc) 606 struct ib_mad_recv_wc *mad_recv_wc)
650{ 607{
@@ -675,11 +632,12 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
675 if (!mad_send_wr) 632 if (!mad_send_wr)
676 goto out; /* Unmatched ACK */ 633 goto out; /* Unmatched ACK */
677 634
678 if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || 635 if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) ||
679 (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) 636 (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
680 goto out; /* Send is already done */ 637 goto out; /* Send is already done */
681 638
682 if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) { 639 if (seg_num > mad_send_wr->send_buf.seg_count ||
640 seg_num > mad_send_wr->newwin) {
683 spin_unlock_irqrestore(&agent->lock, flags); 641 spin_unlock_irqrestore(&agent->lock, flags);
684 abort_send(agent, rmpp_mad->mad_hdr.tid, 642 abort_send(agent, rmpp_mad->mad_hdr.tid,
685 IB_MGMT_RMPP_STATUS_S2B); 643 IB_MGMT_RMPP_STATUS_S2B);
@@ -691,11 +649,11 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
691 goto out; /* Old ACK */ 649 goto out; /* Old ACK */
692 650
693 if (seg_num > mad_send_wr->last_ack) { 651 if (seg_num > mad_send_wr->last_ack) {
694 mad_send_wr->last_ack = seg_num; 652 adjust_last_ack(mad_send_wr, seg_num);
695 mad_send_wr->retries = mad_send_wr->send_buf.retries; 653 mad_send_wr->retries = mad_send_wr->send_buf.retries;
696 } 654 }
697 mad_send_wr->newwin = newwin; 655 mad_send_wr->newwin = newwin;
698 if (mad_send_wr->last_ack == mad_send_wr->total_seg) { 656 if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) {
699 /* If no response is expected, the ACK completes the send */ 657 /* If no response is expected, the ACK completes the send */
700 if (!mad_send_wr->send_buf.timeout_ms) { 658 if (!mad_send_wr->send_buf.timeout_ms) {
701 struct ib_mad_send_wc wc; 659 struct ib_mad_send_wc wc;
@@ -714,7 +672,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
714 mad_send_wr->send_buf.timeout_ms); 672 mad_send_wr->send_buf.timeout_ms);
715 } else if (mad_send_wr->refcount == 1 && 673 } else if (mad_send_wr->refcount == 1 &&
716 mad_send_wr->seg_num < mad_send_wr->newwin && 674 mad_send_wr->seg_num < mad_send_wr->newwin &&
717 mad_send_wr->seg_num <= mad_send_wr->total_seg) { 675 mad_send_wr->seg_num < mad_send_wr->send_buf.seg_count) {
718 /* Send failure will just result in a timeout/retry */ 676 /* Send failure will just result in a timeout/retry */
719 ret = send_next_seg(mad_send_wr); 677 ret = send_next_seg(mad_send_wr);
720 if (ret) 678 if (ret)
@@ -838,31 +796,19 @@ out:
838int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr) 796int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
839{ 797{
840 struct ib_rmpp_mad *rmpp_mad; 798 struct ib_rmpp_mad *rmpp_mad;
841 int i, total_len, ret; 799 int ret;
842 800
843 rmpp_mad = mad_send_wr->send_buf.mad; 801 rmpp_mad = mad_send_wr->send_buf.mad;
844 if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & 802 if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
845 IB_MGMT_RMPP_FLAG_ACTIVE)) 803 IB_MGMT_RMPP_FLAG_ACTIVE))
846 return IB_RMPP_RESULT_UNHANDLED; 804 return IB_RMPP_RESULT_UNHANDLED;
847 805
848 if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) 806 if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
807 mad_send_wr->seg_num = 1;
849 return IB_RMPP_RESULT_INTERNAL; 808 return IB_RMPP_RESULT_INTERNAL;
809 }
850 810
851 if (mad_send_wr->send_wr.num_sge > 1)
852 return -EINVAL; /* TODO: support num_sge > 1 */
853
854 mad_send_wr->seg_num = 1;
855 mad_send_wr->newwin = 1; 811 mad_send_wr->newwin = 1;
856 mad_send_wr->data_offset = data_offset(rmpp_mad->mad_hdr.mgmt_class);
857
858 total_len = 0;
859 for (i = 0; i < mad_send_wr->send_wr.num_sge; i++)
860 total_len += mad_send_wr->send_wr.sg_list[i].length;
861
862 mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
863 (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
864 mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR -
865 be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
866 812
867 /* We need to wait for the final ACK even if there isn't a response */ 813 /* We need to wait for the final ACK even if there isn't a response */
868 mad_send_wr->refcount += (mad_send_wr->timeout == 0); 814 mad_send_wr->refcount += (mad_send_wr->timeout == 0);
@@ -893,14 +839,14 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
893 if (!mad_send_wr->timeout) 839 if (!mad_send_wr->timeout)
894 return IB_RMPP_RESULT_PROCESSED; /* Response received */ 840 return IB_RMPP_RESULT_PROCESSED; /* Response received */
895 841
896 if (mad_send_wr->last_ack == mad_send_wr->total_seg) { 842 if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) {
897 mad_send_wr->timeout = 843 mad_send_wr->timeout =
898 msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); 844 msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
899 return IB_RMPP_RESULT_PROCESSED; /* Send done */ 845 return IB_RMPP_RESULT_PROCESSED; /* Send done */
900 } 846 }
901 847
902 if (mad_send_wr->seg_num > mad_send_wr->newwin || 848 if (mad_send_wr->seg_num == mad_send_wr->newwin ||
903 mad_send_wr->seg_num > mad_send_wr->total_seg) 849 mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count)
904 return IB_RMPP_RESULT_PROCESSED; /* Wait for ACK */ 850 return IB_RMPP_RESULT_PROCESSED; /* Wait for ACK */
905 851
906 ret = send_next_seg(mad_send_wr); 852 ret = send_next_seg(mad_send_wr);
@@ -921,10 +867,12 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr)
921 IB_MGMT_RMPP_FLAG_ACTIVE)) 867 IB_MGMT_RMPP_FLAG_ACTIVE))
922 return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */ 868 return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
923 869
924 if (mad_send_wr->last_ack == mad_send_wr->total_seg) 870 if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count)
925 return IB_RMPP_RESULT_PROCESSED; 871 return IB_RMPP_RESULT_PROCESSED;
926 872
927 mad_send_wr->seg_num = mad_send_wr->last_ack + 1; 873 mad_send_wr->seg_num = mad_send_wr->last_ack;
874 mad_send_wr->cur_seg = mad_send_wr->last_ack_seg;
875
928 ret = send_next_seg(mad_send_wr); 876 ret = send_next_seg(mad_send_wr);
929 if (ret) 877 if (ret)
930 return IB_RMPP_RESULT_PROCESSED; 878 return IB_RMPP_RESULT_PROCESSED;