int ret = 0;
int can_wait = gfp & __GFP_WAIT;
int must_wake = 0;
+ int ring_low = 0;
+ int ring_empty = 0;
u32 pos;
/*
if (!acquire_refill(conn))
return;
+ ring_low = rds_ib_ring_low(&ic->i_recv_ring);
+ ring_empty = rds_ib_ring_empty(&ic->i_recv_ring);
+
+ /* If we ever end up with a really empty receive ring, we're
+ * in deep trouble, as the sender will definitely see RNR
+ * timeouts. */
+ if (ring_empty)
+ rds_ib_stats_inc(s_ib_rx_ring_empty);
+
+ /*
+ * if we're called from the tasklet, can_wait will be zero. We only
+ * want to refill if we're getting low in this case
+ */
+ if (!ring_low && !can_wait)
+ goto release_out;
+
while ((prefill || rds_conn_up(conn))
&& rds_ib_ring_alloc(&ic->i_recv_ring, 1, &pos)) {
if (pos >= ic->i_recv_ring.w_nr) {
}
}
+ /* read ring_low and ring_empty before we drop our lock */
+ ring_low = rds_ib_ring_low(&ic->i_recv_ring);
+ ring_empty = rds_ib_ring_empty(&ic->i_recv_ring);
+
/* We're doing flow control - update the window. */
if (ic->i_flowctl && posted)
rds_ib_advertise_credits(conn, posted);
if (ret)
rds_ib_ring_unalloc(&ic->i_recv_ring, 1);
+release_out:
release_refill(conn);
/* if we're called from the softirq handler, we'll be GFP_NOWAIT.
* if we should requeue.
*/
if (rds_conn_up(conn) &&
- (must_wake ||
- (can_wait && rds_ib_ring_low(&ic->i_recv_ring)) ||
- rds_ib_ring_empty(&ic->i_recv_ring))) {
+ (must_wake || (can_wait && ring_low) || ring_empty)) {
queue_delayed_work(rds_wq, &conn->c_recv_w, 1);
}
if (can_wait)
}
rds_ib_ring_free(&ic->i_recv_ring, 1);
- /* If we ever end up with a really empty receive ring, we're
- * in deep trouble, as the sender will definitely see RNR
- * timeouts. */
- if (rds_ib_ring_empty(&ic->i_recv_ring))
- rds_ib_stats_inc(s_ib_rx_ring_empty);
-
- if (rds_ib_ring_low(&ic->i_recv_ring))
- rds_ib_recv_refill(conn, 0, GFP_NOWAIT);
+ rds_ib_recv_refill(conn, 0, GFP_NOWAIT);
}
int rds_ib_recv(struct rds_connection *conn)