aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/iw_recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rds/iw_recv.c')
-rw-r--r--net/rds/iw_recv.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c
index 8683f5f66c4b..54af7d6b92da 100644
--- a/net/rds/iw_recv.c
+++ b/net/rds/iw_recv.c
@@ -143,15 +143,16 @@ static int rds_iw_recv_refill_one(struct rds_connection *conn,
143 int ret = -ENOMEM; 143 int ret = -ENOMEM;
144 144
145 if (recv->r_iwinc == NULL) { 145 if (recv->r_iwinc == NULL) {
146 if (atomic_read(&rds_iw_allocation) >= rds_iw_sysctl_max_recv_allocation) { 146 if (!atomic_add_unless(&rds_iw_allocation, 1, rds_iw_sysctl_max_recv_allocation)) {
147 rds_iw_stats_inc(s_iw_rx_alloc_limit); 147 rds_iw_stats_inc(s_iw_rx_alloc_limit);
148 goto out; 148 goto out;
149 } 149 }
150 recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab, 150 recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab,
151 kptr_gfp); 151 kptr_gfp);
152 if (recv->r_iwinc == NULL) 152 if (recv->r_iwinc == NULL) {
153 atomic_dec(&rds_iw_allocation);
153 goto out; 154 goto out;
154 atomic_inc(&rds_iw_allocation); 155 }
155 INIT_LIST_HEAD(&recv->r_iwinc->ii_frags); 156 INIT_LIST_HEAD(&recv->r_iwinc->ii_frags);
156 rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr); 157 rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr);
157 } 158 }
@@ -229,8 +230,8 @@ int rds_iw_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
229 int ret = 0; 230 int ret = 0;
230 u32 pos; 231 u32 pos;
231 232
232 while ((prefill || rds_conn_up(conn)) 233 while ((prefill || rds_conn_up(conn)) &&
233 && rds_iw_ring_alloc(&ic->i_recv_ring, 1, &pos)) { 234 rds_iw_ring_alloc(&ic->i_recv_ring, 1, &pos)) {
234 if (pos >= ic->i_recv_ring.w_nr) { 235 if (pos >= ic->i_recv_ring.w_nr) {
235 printk(KERN_NOTICE "Argh - ring alloc returned pos=%u\n", 236 printk(KERN_NOTICE "Argh - ring alloc returned pos=%u\n",
236 pos); 237 pos);
@@ -729,10 +730,10 @@ static void rds_iw_process_recv(struct rds_connection *conn,
729 hdr = &iwinc->ii_inc.i_hdr; 730 hdr = &iwinc->ii_inc.i_hdr;
730 /* We can't just use memcmp here; fragments of a 731 /* We can't just use memcmp here; fragments of a
731 * single message may carry different ACKs */ 732 * single message may carry different ACKs */
732 if (hdr->h_sequence != ihdr->h_sequence 733 if (hdr->h_sequence != ihdr->h_sequence ||
733 || hdr->h_len != ihdr->h_len 734 hdr->h_len != ihdr->h_len ||
734 || hdr->h_sport != ihdr->h_sport 735 hdr->h_sport != ihdr->h_sport ||
735 || hdr->h_dport != ihdr->h_dport) { 736 hdr->h_dport != ihdr->h_dport) {
736 rds_iw_conn_error(conn, 737 rds_iw_conn_error(conn,
737 "fragment header mismatch; forcing reconnect\n"); 738 "fragment header mismatch; forcing reconnect\n");
738 return; 739 return;
@@ -783,17 +784,22 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context)
783{ 784{
784 struct rds_connection *conn = context; 785 struct rds_connection *conn = context;
785 struct rds_iw_connection *ic = conn->c_transport_data; 786 struct rds_iw_connection *ic = conn->c_transport_data;
786 struct ib_wc wc;
787 struct rds_iw_ack_state state = { 0, };
788 struct rds_iw_recv_work *recv;
789 787
790 rdsdebug("conn %p cq %p\n", conn, cq); 788 rdsdebug("conn %p cq %p\n", conn, cq);
791 789
792 rds_iw_stats_inc(s_iw_rx_cq_call); 790 rds_iw_stats_inc(s_iw_rx_cq_call);
793 791
794 ib_req_notify_cq(cq, IB_CQ_SOLICITED); 792 tasklet_schedule(&ic->i_recv_tasklet);
793}
794
795static inline void rds_poll_cq(struct rds_iw_connection *ic,
796 struct rds_iw_ack_state *state)
797{
798 struct rds_connection *conn = ic->conn;
799 struct ib_wc wc;
800 struct rds_iw_recv_work *recv;
795 801
796 while (ib_poll_cq(cq, 1, &wc) > 0) { 802 while (ib_poll_cq(ic->i_recv_cq, 1, &wc) > 0) {
797 rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", 803 rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n",
798 (unsigned long long)wc.wr_id, wc.status, wc.byte_len, 804 (unsigned long long)wc.wr_id, wc.status, wc.byte_len,
799 be32_to_cpu(wc.ex.imm_data)); 805 be32_to_cpu(wc.ex.imm_data));
@@ -811,7 +817,7 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context)
811 if (rds_conn_up(conn) || rds_conn_connecting(conn)) { 817 if (rds_conn_up(conn) || rds_conn_connecting(conn)) {
812 /* We expect errors as the qp is drained during shutdown */ 818 /* We expect errors as the qp is drained during shutdown */
813 if (wc.status == IB_WC_SUCCESS) { 819 if (wc.status == IB_WC_SUCCESS) {
814 rds_iw_process_recv(conn, recv, wc.byte_len, &state); 820 rds_iw_process_recv(conn, recv, wc.byte_len, state);
815 } else { 821 } else {
816 rds_iw_conn_error(conn, "recv completion on " 822 rds_iw_conn_error(conn, "recv completion on "
817 "%pI4 had status %u, disconnecting and " 823 "%pI4 had status %u, disconnecting and "
@@ -822,6 +828,17 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context)
822 828
823 rds_iw_ring_free(&ic->i_recv_ring, 1); 829 rds_iw_ring_free(&ic->i_recv_ring, 1);
824 } 830 }
831}
832
833void rds_iw_recv_tasklet_fn(unsigned long data)
834{
835 struct rds_iw_connection *ic = (struct rds_iw_connection *) data;
836 struct rds_connection *conn = ic->conn;
837 struct rds_iw_ack_state state = { 0, };
838
839 rds_poll_cq(ic, &state);
840 ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED);
841 rds_poll_cq(ic, &state);
825 842
826 if (state.ack_next_valid) 843 if (state.ack_next_valid)
827 rds_iw_set_ack(ic, state.ack_next, state.ack_required); 844 rds_iw_set_ack(ic, state.ack_next, state.ack_required);