Example #1
0
static inline uint64_t
select_ddp_flags(struct socket *so, int flags, int db_idx)
{
    uint64_t ddp_flags = V_TF_DDP_INDICATE_OUT(0);
    int waitall = flags & MSG_WAITALL;
    int nb = so->so_state & SS_NBIO || flags & (MSG_DONTWAIT | MSG_NBIO);

    KASSERT(db_idx == 0 || db_idx == 1,
            ("%s: bad DDP buffer index %d", __func__, db_idx));

    if (db_idx == 0) {
        ddp_flags |= V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_ACTIVE_BUF(0);
        if (waitall)
            ddp_flags |= V_TF_DDP_PUSH_DISABLE_0(1);
        else if (nb)
            ddp_flags |= V_TF_DDP_BUF0_FLUSH(1);
        else
            ddp_flags |= V_TF_DDP_BUF0_FLUSH(0);
    } else {
        ddp_flags |= V_TF_DDP_BUF1_VALID(1) | V_TF_DDP_ACTIVE_BUF(1);
        if (waitall)
            ddp_flags |= V_TF_DDP_PUSH_DISABLE_1(1);
        else if (nb)
            ddp_flags |= V_TF_DDP_BUF1_FLUSH(1);
        else
            ddp_flags |= V_TF_DDP_BUF1_FLUSH(0);
    }

    return (ddp_flags);
}
static __inline unsigned long
select_ddp_flags(const struct toepcb *toep, int buf_idx,
                 int nonblock, int rcv_flags)
{
	if (buf_idx == 1) {
		if (__predict_false(rcv_flags & MSG_WAITALL))
			return V_TF_DDP_PSH_NO_INVALIDATE0(1) |
			       V_TF_DDP_PSH_NO_INVALIDATE1(1) |
			       V_TF_DDP_PUSH_DISABLE_1(1);
		if (nonblock)
			return V_TF_DDP_BUF1_FLUSH(1);

		return V_TF_DDP_BUF1_FLUSH(!TOM_TUNABLE(toep->tp_toedev,
							ddp_push_wait));
	}

	if (__predict_false(rcv_flags & MSG_WAITALL))
		return V_TF_DDP_PSH_NO_INVALIDATE0(1) |
		       V_TF_DDP_PSH_NO_INVALIDATE1(1) |
		       V_TF_DDP_PUSH_DISABLE_0(1);
	if (nonblock)
		return V_TF_DDP_BUF0_FLUSH(1);

	return V_TF_DDP_BUF0_FLUSH(!TOM_TUNABLE(toep->tp_toedev, ddp_push_wait));
}
/*
 * Reposts the kernel DDP buffer after it has been previously become full and
 * invalidated.  We just need to reset the offset and adjust the DDP flags.
 * Conveniently, we can set the flags and the offset with a single message.
 * Note that this function does not set the buffer length.  Again conveniently
 * our kernel buffer is of fixed size.  If the length needs to be changed it
 * needs to be done separately.
 */
static void
t3_repost_kbuf(struct toepcb *toep, unsigned int bufidx, int modulate, 
    int activate, int nonblock)
{
	struct ddp_state *p = &toep->tp_ddp_state;
	unsigned long flags;

#if 0	
	SOCKBUF_LOCK_ASSERT(&so->so_rcv);
#endif	
	p->buf_state[bufidx].cur_offset = p->kbuf[bufidx]->dgl_offset;
	p->buf_state[bufidx].flags = p->kbuf_noinval ? DDP_BF_NOINVAL : 0;
	p->buf_state[bufidx].gl = p->kbuf[bufidx];
	p->cur_buf = bufidx;
	p->kbuf_idx = bufidx;

	flags = select_ddp_flags(toep, bufidx, nonblock, 0);
	if (!bufidx)
		t3_setup_ddpbufs(toep, 0, 0, 0, 0, flags |
			 V_TF_DDP_PSH_NO_INVALIDATE0(p->kbuf_noinval) |
			 V_TF_DDP_PSH_NO_INVALIDATE1(p->kbuf_noinval) |
		         V_TF_DDP_BUF0_VALID(1),
		         V_TF_DDP_BUF0_FLUSH(1) |
			 V_TF_DDP_PSH_NO_INVALIDATE0(1) |
		         V_TF_DDP_PSH_NO_INVALIDATE1(1) | V_TF_DDP_OFF(1) |
			 V_TF_DDP_BUF0_VALID(1) |
			 V_TF_DDP_ACTIVE_BUF(activate), modulate);
	else
		t3_setup_ddpbufs(toep, 0, 0, 0, 0, flags |
			 V_TF_DDP_PSH_NO_INVALIDATE0(p->kbuf_noinval) |	
		         V_TF_DDP_PSH_NO_INVALIDATE1(p->kbuf_noinval) | 
			 V_TF_DDP_BUF1_VALID(1) | 
			 V_TF_DDP_ACTIVE_BUF(activate),
		         V_TF_DDP_BUF1_FLUSH(1) | 
			 V_TF_DDP_PSH_NO_INVALIDATE0(1) |
		         V_TF_DDP_PSH_NO_INVALIDATE1(1) | V_TF_DDP_OFF(1) |
			 V_TF_DDP_BUF1_VALID(1) | V_TF_DDP_ACTIVE_BUF(1), 
			 modulate);
	
}
Example #4
0
static struct wrqe *
mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx,
                      int offset, uint64_t ddp_flags)
{
    struct ddp_buffer *db = toep->db[db_idx];
    struct wrqe *wr;
    struct work_request_hdr *wrh;
    struct ulp_txpkt *ulpmc;
    int len;

    KASSERT(db_idx == 0 || db_idx == 1,
            ("%s: bad DDP buffer index %d", __func__, db_idx));

    /*
     * We'll send a compound work request that has 3 SET_TCB_FIELDs and an
     * RX_DATA_ACK (with RX_MODULATE to speed up delivery).
     *
     * The work request header is 16B and always ends at a 16B boundary.
     * The ULPTX master commands that follow must all end at 16B boundaries
     * too so we round up the size to 16.
     */
    len = sizeof(*wrh) + 3 * roundup2(LEN__SET_TCB_FIELD_ULP, 16) +
          roundup2(LEN__RX_DATA_ACK_ULP, 16);

    wr = alloc_wrqe(len, toep->ctrlq);
    if (wr == NULL)
        return (NULL);
    wrh = wrtod(wr);
    INIT_ULPTX_WRH(wrh, len, 1, 0);	/* atomic */
    ulpmc = (struct ulp_txpkt *)(wrh + 1);

    /* Write the buffer's tag */
    ulpmc = mk_set_tcb_field_ulp(ulpmc, toep,
                                 W_TCB_RX_DDP_BUF0_TAG + db_idx,
                                 V_TCB_RX_DDP_BUF0_TAG(M_TCB_RX_DDP_BUF0_TAG),
                                 V_TCB_RX_DDP_BUF0_TAG(db->tag));

    /* Update the current offset in the DDP buffer and its total length */
    if (db_idx == 0)
        ulpmc = mk_set_tcb_field_ulp(ulpmc, toep,
                                     W_TCB_RX_DDP_BUF0_OFFSET,
                                     V_TCB_RX_DDP_BUF0_OFFSET(M_TCB_RX_DDP_BUF0_OFFSET) |
                                     V_TCB_RX_DDP_BUF0_LEN(M_TCB_RX_DDP_BUF0_LEN),
                                     V_TCB_RX_DDP_BUF0_OFFSET(offset) |
                                     V_TCB_RX_DDP_BUF0_LEN(db->len));
    else
        ulpmc = mk_set_tcb_field_ulp(ulpmc, toep,
                                     W_TCB_RX_DDP_BUF1_OFFSET,
                                     V_TCB_RX_DDP_BUF1_OFFSET(M_TCB_RX_DDP_BUF1_OFFSET) |
                                     V_TCB_RX_DDP_BUF1_LEN((u64)M_TCB_RX_DDP_BUF1_LEN << 32),
                                     V_TCB_RX_DDP_BUF1_OFFSET(offset) |
                                     V_TCB_RX_DDP_BUF1_LEN((u64)db->len << 32));

    /* Update DDP flags */
    ulpmc = mk_set_tcb_field_ulp(ulpmc, toep, W_TCB_RX_DDP_FLAGS,
                                 V_TF_DDP_BUF0_FLUSH(1) | V_TF_DDP_BUF1_FLUSH(1) |
                                 V_TF_DDP_PUSH_DISABLE_0(1) | V_TF_DDP_PUSH_DISABLE_1(1) |
                                 V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_BUF1_VALID(1) |
                                 V_TF_DDP_ACTIVE_BUF(1) | V_TF_DDP_INDICATE_OUT(1), ddp_flags);

    /* Gratuitous RX_DATA_ACK with RX_MODULATE set to speed up delivery. */
    ulpmc = mk_rx_data_ack_ulp(ulpmc, toep);

    return (wr);
}