Beispiel #1
0
/* Link down event*/
static void
ntb_transport_link_cleanup(struct ntb_netdev *nt)
{
	int i;

	if (nt->transport_link == NTB_LINK_DOWN)
		callout_drain(&nt->link_work);
	else
		nt->transport_link = NTB_LINK_DOWN;

	/* Pass along the info to any clients */
	for (i = 0; i < nt->max_qps; i++)
		if (!test_bit(i, &nt->qp_bitmap))
			ntb_qp_link_down(&nt->qps[i]);

	/* 
	 * The scratchpad registers keep the values if the remote side
	 * goes down, blast them now to give them a sane value the next
	 * time they are accessed
	 */
	for (i = 0; i < IF_NTB_MAX_SPAD; i++)
		ntb_write_local_spad(nt->ntb, i, 0);
}
Beispiel #2
0
static int
ntb_process_rxc(struct ntb_transport_qp *qp)
{
	struct ntb_payload_header *hdr;
	struct ntb_queue_entry *entry;
	void *offset;

	offset = (void *)
	    ((char *)qp->rx_buff + qp->rx_max_frame * qp->rx_index);
	hdr = (void *)
	    ((char *)offset + qp->rx_max_frame -
		sizeof(struct ntb_payload_header));

	CTR1(KTR_NTB, "RX: process_rxc rx_index = %u", qp->rx_index);
	entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q);
	if (entry == NULL) {
		qp->rx_err_no_buf++;
		CTR0(KTR_NTB, "RX: No entries in rx_pend_q");
		return (ENOMEM);
	}
	callout_stop(&qp->rx_full);
	CTR1(KTR_NTB, "RX: rx entry %p from rx_pend_q", entry);

	if ((hdr->flags & IF_NTB_DESC_DONE_FLAG) == 0) {
		CTR1(KTR_NTB,
		    "RX: hdr not done. Returning entry %p to rx_pend_q", entry);
		ntb_list_add(&qp->ntb_rx_pend_q_lock, entry, &qp->rx_pend_q);
		qp->rx_ring_empty++;
		return (EAGAIN);
	}

	if (hdr->ver != (uint32_t) qp->rx_pkts) {
		CTR3(KTR_NTB,"RX: ver != rx_pkts (%x != %lx). "
		    "Returning entry %p to rx_pend_q", hdr->ver, qp->rx_pkts,
		    entry);
		ntb_list_add(&qp->ntb_rx_pend_q_lock, entry, &qp->rx_pend_q);
		qp->rx_err_ver++;
		return (EIO);
	}

	if ((hdr->flags & IF_NTB_LINK_DOWN_FLAG) != 0) {
		ntb_qp_link_down(qp);
		CTR1(KTR_NTB,
		    "RX: link down. adding entry %p back to rx_pend_q", entry);
		ntb_list_add(&qp->ntb_rx_pend_q_lock, entry, &qp->rx_pend_q);
		goto out;
	}

	if (hdr->len <= entry->len) {
		entry->len = hdr->len;
		ntb_rx_copy_task(qp, entry, offset);
	} else {
		CTR1(KTR_NTB,
		    "RX: len too long. Returning entry %p to rx_pend_q", entry);
		ntb_list_add(&qp->ntb_rx_pend_q_lock, entry, &qp->rx_pend_q);

		qp->rx_err_oflow++;
	}

	qp->rx_bytes += hdr->len;
	qp->rx_pkts++;
	CTR1(KTR_NTB, "RX: received %ld rx_pkts", qp->rx_pkts);


out:
	/* Ensure that the data is globally visible before clearing the flag */
	wmb();
	hdr->flags = 0;
	/* TODO: replace with bus_space_write */
	qp->rx_info->entry = qp->rx_index;

	qp->rx_index++;
	qp->rx_index %= qp->rx_max_entry;

	return (0);
}
Beispiel #3
0
static int
ntb_process_rxc(struct ntb_transport_qp *qp)
{
	struct ntb_payload_header *hdr;
	struct ntb_queue_entry *entry;
	caddr_t offset;

	offset = qp->rx_buff + qp->rx_max_frame * qp->rx_index;
	hdr = (void *)(offset + qp->rx_max_frame -
	    sizeof(struct ntb_payload_header));

	CTR1(KTR_NTB, "RX: process_rxc rx_index = %u", qp->rx_index);
	if ((hdr->flags & IF_NTB_DESC_DONE_FLAG) == 0) {
		CTR0(KTR_NTB, "RX: hdr not done");
		qp->rx_ring_empty++;
		return (EAGAIN);
	}

	if ((hdr->flags & IF_NTB_LINK_DOWN_FLAG) != 0) {
		CTR0(KTR_NTB, "RX: link down");
		ntb_qp_link_down(qp);
		hdr->flags = 0;
		return (EAGAIN);
	}

	if (hdr->ver != (uint32_t)qp->rx_pkts) {
		CTR2(KTR_NTB,"RX: ver != rx_pkts (%x != %lx). "
		    "Returning entry to rx_pend_q", hdr->ver, qp->rx_pkts);
		qp->rx_err_ver++;
		return (EIO);
	}

	entry = ntb_list_mv(&qp->ntb_rx_q_lock, &qp->rx_pend_q, &qp->rx_post_q);
	if (entry == NULL) {
		qp->rx_err_no_buf++;
		CTR0(KTR_NTB, "RX: No entries in rx_pend_q");
		return (EAGAIN);
	}
	callout_stop(&qp->rx_full);
	CTR1(KTR_NTB, "RX: rx entry %p from rx_pend_q", entry);

	entry->x_hdr = hdr;
	entry->index = qp->rx_index;

	if (hdr->len > entry->len) {
		CTR2(KTR_NTB, "RX: len too long. Wanted %ju got %ju",
		    (uintmax_t)hdr->len, (uintmax_t)entry->len);
		qp->rx_err_oflow++;

		entry->len = -EIO;
		entry->flags |= IF_NTB_DESC_DONE_FLAG;

		taskqueue_enqueue(taskqueue_swi, &qp->rx_completion_task);
	} else {
		qp->rx_bytes += hdr->len;
		qp->rx_pkts++;

		CTR1(KTR_NTB, "RX: received %ld rx_pkts", qp->rx_pkts);

		entry->len = hdr->len;

		ntb_memcpy_rx(qp, entry, offset);
	}

	qp->rx_index++;
	qp->rx_index %= qp->rx_max_entry;
	return (0);
}