[rds-devel] comments on the send CQ completion handler
Or Gerlitz
ogerlitz at voltaire.com
Tue Jan 8 06:42:30 PST 2008
Hi Olaf,
Looking on rds_ib_send_cq_comp_handler I see few issues, see my inline comments:
+void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context)
+{
+ struct rds_connection *conn = context;
+ struct rds_ib_connection *ic = conn->c_transport_data;
+ struct ib_wc wc;
+ struct rds_ib_send_work *send;
+ u32 completed;
+ u32 oldest;
+ u32 i = 0;
+ int ret;
+
+ rdsdebug("cq %p conn %p\n", cq, conn);
+ rds_ib_stats_inc(s_ib_tx_cq_call);
+ ret = ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+ if (ret) {
+ rdsdebug("ib_req_notify_cq send failed: %d\n", ret);
+ }
+
+ while (ib_poll_cq(cq, 1, &wc) > 0 ) {
+ rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n",
+ (unsigned long long)wc.wr_id, wc.status, wc.byte_len,
+ be32_to_cpu(wc.imm_data));
+ rds_ib_stats_inc(s_ib_tx_cq_event);
+
+ if (wc.wr_id == ~0) {
+ if (ic->i_ack_queued + HZ/2 < jiffies)
+ rds_ib_stats_inc(s_ib_tx_stalled);
+ rds_ib_ack_send_complete(ic);
+ continue;
+ }
+
+ oldest = rds_ib_ring_oldest(&ic->i_send_ring);
+ send = &ic->i_sends[oldest];
+
+ completed = rds_ib_ring_completed(&ic->i_send_ring, wc.wr_id, oldest);
+
+ for (i = 0; i < completed; i++) {
+ if (wc.opcode == IB_WC_SEND) {
+ if (send->s_rm)
+ rds_ib_send_unmap_rm(ic, send);
+ }
+ else if (wc.opcode == IB_WC_RDMA_WRITE) {
+ if (send->s_op)
+ dma_unmap_sg(ic->i_cm_id->device->dma_device,
+ send->s_op->r_sg, send->s_op->r_nents,
+ DMA_TO_DEVICE);
+ }
+ else if (wc.opcode == IB_WC_RDMA_READ) {
+ if (send->s_op)
+ dma_unmap_sg(ic->i_cm_id->device->dma_device,
+ send->s_op->r_sg, send->s_op->r_nents,
+ DMA_FROM_DEVICE);
+ }
This wc actually represents $completed completions so the value of wc.opcode is only
relevant for the --last-- iteration, a quite easy fix for that would be to mark the
opcode at the send strucutre.
+
+ send->s_wr.num_sge = 1;
+ if (send->s_queued + HZ/2 < jiffies)
+ rds_ib_stats_inc(s_ib_tx_stalled);
+ if (++send == &ic->i_sends[ic->i_send_ring.w_nr])
+ send = ic->i_sends;
+ }
+ rds_ib_ring_free(&ic->i_send_ring, completed);
+
+ if (test_and_clear_bit(RDS_LL_SEND_FULL, &conn->c_flags))
+ queue_delayed_work(rds_wq, &conn->c_send_w, 0);
+
+ /* We expect errors as the qp is drained during shutdown */
+ if (wc.status != IB_WC_SUCCESS && rds_conn_up(conn)) {
+ rds_ib_conn_error(conn,
+ "completion on %u.%u.%u.%u "
+ "had status %u, disconnecting and reconnecting\n",
+ NIPQUAD(conn->c_faddr), wc.status);
+ }
if wc.status is not success then all the other fields (speficially opcode) are invalid
except for the wr_id, an easy fix would be to move that check to be following the call
to ib_poll_cq, agree?
+ }
+}
Or.
More information about the rds-devel
mailing list