예제 #1
0
static int
ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt, unsigned int qp_num)
{
	struct ntb_transport_qp *qp = &nt->qp_vec[qp_num];
	struct ntb_transport_mw *mw;
	void *offset;
	ntb_q_idx_t i;
	size_t rx_size;
	unsigned num_qps_mw, mw_num, mw_count;

	mw_count = nt->mw_count;
	mw_num = QP_TO_MW(nt, qp_num);
	mw = &nt->mw_vec[mw_num];

	if (mw->virt_addr == NULL)
		return (ENOMEM);

	if (nt->qp_count % mw_count && mw_num + 1 < nt->qp_count / mw_count)
		num_qps_mw = nt->qp_count / mw_count + 1;
	else
		num_qps_mw = nt->qp_count / mw_count;

	rx_size = mw->xlat_size / num_qps_mw;
	qp->rx_buff = mw->virt_addr + rx_size * (qp_num / mw_count);
	rx_size -= sizeof(struct ntb_rx_info);

	qp->remote_rx_info = (void*)(qp->rx_buff + rx_size);

	/* Due to house-keeping, there must be at least 2 buffs */
	qp->rx_max_frame = qmin(rx_size / 2,
	    transport_mtu + sizeof(struct ntb_payload_header));
	qp->rx_max_entry = rx_size / qp->rx_max_frame;
	qp->rx_index = 0;

	qp->remote_rx_info->entry = qp->rx_max_entry - 1;

	/* Set up the hdr offsets with 0s */
	for (i = 0; i < qp->rx_max_entry; i++) {
		offset = (void *)(qp->rx_buff + qp->rx_max_frame * (i + 1) -
		    sizeof(struct ntb_payload_header));
		memset(offset, 0, sizeof(struct ntb_payload_header));
	}

	qp->rx_pkts = 0;
	qp->tx_pkts = 0;
	qp->tx_index = 0;

	return (0);
}
예제 #2
0
static void
ntb_transport_init_queue(struct ntb_netdev *nt, unsigned int qp_num)
{
	struct ntb_transport_qp *qp;
	unsigned int num_qps_mw, tx_size;
	uint8_t mw_num = QP_TO_MW(qp_num);

	qp = &nt->qps[qp_num];
	qp->qp_num = qp_num;
	qp->transport = nt;
	qp->ntb = nt->ntb;
	qp->qp_link = NTB_LINK_DOWN;
	qp->client_ready = NTB_LINK_DOWN;
	qp->event_handler = NULL;

	if (nt->max_qps % NTB_NUM_MW && mw_num < nt->max_qps % NTB_NUM_MW)
		num_qps_mw = nt->max_qps / NTB_NUM_MW + 1;
	else
		num_qps_mw = nt->max_qps / NTB_NUM_MW;

	tx_size = (unsigned int) ntb_get_mw_size(qp->ntb, mw_num) / num_qps_mw;
	qp->rx_info = (struct ntb_rx_info *)
	    ((char *)ntb_get_mw_vbase(qp->ntb, mw_num) +
	    (qp_num / NTB_NUM_MW * tx_size));
	tx_size -= sizeof(struct ntb_rx_info);

	qp->tx_mw = qp->rx_info + sizeof(struct ntb_rx_info);
	qp->tx_max_frame = min(transport_mtu + sizeof(struct ntb_payload_header),
	    tx_size);
	qp->tx_max_entry = tx_size / qp->tx_max_frame;
	qp->tx_index = 0;

	callout_init(&qp->link_work, 0);
	callout_init(&qp->queue_full, CALLOUT_MPSAFE);
	callout_init(&qp->rx_full, CALLOUT_MPSAFE);

	mtx_init(&qp->ntb_rx_pend_q_lock, "ntb rx pend q", NULL, MTX_SPIN);
	mtx_init(&qp->ntb_rx_free_q_lock, "ntb rx free q", NULL, MTX_SPIN);
	mtx_init(&qp->ntb_tx_free_q_lock, "ntb tx free q", NULL, MTX_SPIN);
	TASK_INIT(&qp->rx_completion_task, 0, ntb_rx_completion_task, qp);

	STAILQ_INIT(&qp->rx_pend_q);
	STAILQ_INIT(&qp->rx_free_q);
	STAILQ_INIT(&qp->tx_free_q);
}
예제 #3
0
static void
ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num)
{
	struct ntb_transport_qp *qp = &nt->qps[qp_num];
	void *offset;
	unsigned int rx_size, num_qps_mw;
	uint8_t mw_num = QP_TO_MW(qp_num);
	unsigned int i;

	if (nt->max_qps % NTB_NUM_MW && mw_num < nt->max_qps % NTB_NUM_MW)
		num_qps_mw = nt->max_qps / NTB_NUM_MW + 1;
	else
		num_qps_mw = nt->max_qps / NTB_NUM_MW;

	rx_size = (unsigned int) nt->mw[mw_num].size / num_qps_mw;
	qp->remote_rx_info = (void *)((uint8_t *)nt->mw[mw_num].virt_addr +
			     (qp_num / NTB_NUM_MW * rx_size));
	rx_size -= sizeof(struct ntb_rx_info);

	qp->rx_buff = qp->remote_rx_info + sizeof(struct ntb_rx_info);
	qp->rx_max_frame = min(transport_mtu + sizeof(struct ntb_payload_header),
	    rx_size);
	qp->rx_max_entry = rx_size / qp->rx_max_frame;
	qp->rx_index = 0;
	qp->tx_index = 0;

	qp->remote_rx_info->entry = qp->rx_max_entry;

	/* setup the hdr offsets with 0's */
	for (i = 0; i < qp->rx_max_entry; i++) {
		offset = (void *)((uint8_t *)qp->rx_buff +
		    qp->rx_max_frame * (i + 1) -
		    sizeof(struct ntb_payload_header));
		memset(offset, 0, sizeof(struct ntb_payload_header));
	}

	qp->rx_pkts = 0;
	qp->tx_pkts = 0;
}
예제 #4
0
static void
ntb_transport_init_queue(struct ntb_transport_ctx *nt, unsigned int qp_num)
{
	struct ntb_transport_mw *mw;
	struct ntb_transport_qp *qp;
	vm_paddr_t mw_base;
	uint64_t mw_size, qp_offset;
	size_t tx_size;
	unsigned num_qps_mw, mw_num, mw_count;

	mw_count = nt->mw_count;
	mw_num = QP_TO_MW(nt, qp_num);
	mw = &nt->mw_vec[mw_num];

	qp = &nt->qp_vec[qp_num];
	qp->qp_num = qp_num;
	qp->transport = nt;
	qp->ntb = nt->ntb;
	qp->client_ready = false;
	qp->event_handler = NULL;
	ntb_qp_link_down_reset(qp);

	if (nt->qp_count % mw_count && mw_num + 1 < nt->qp_count / mw_count)
		num_qps_mw = nt->qp_count / mw_count + 1;
	else
		num_qps_mw = nt->qp_count / mw_count;

	mw_base = mw->phys_addr;
	mw_size = mw->phys_size;

	tx_size = mw_size / num_qps_mw;
	qp_offset = tx_size * (qp_num / mw_count);

	qp->tx_mw = mw->vbase + qp_offset;
	KASSERT(qp->tx_mw != NULL, ("uh oh?"));

	/* XXX Assumes that a vm_paddr_t is equivalent to bus_addr_t */
	qp->tx_mw_phys = mw_base + qp_offset;
	KASSERT(qp->tx_mw_phys != 0, ("uh oh?"));

	tx_size -= sizeof(struct ntb_rx_info);
	qp->rx_info = (void *)(qp->tx_mw + tx_size);

	/* Due to house-keeping, there must be at least 2 buffs */
	qp->tx_max_frame = qmin(tx_size / 2,
	    transport_mtu + sizeof(struct ntb_payload_header));
	qp->tx_max_entry = tx_size / qp->tx_max_frame;

	callout_init(&qp->link_work, 0);
	callout_init(&qp->queue_full, 1);
	callout_init(&qp->rx_full, 1);

	mtx_init(&qp->ntb_rx_q_lock, "ntb rx q", NULL, MTX_SPIN);
	mtx_init(&qp->ntb_tx_free_q_lock, "ntb tx free q", NULL, MTX_SPIN);
	TASK_INIT(&qp->rx_completion_task, 0, ntb_complete_rxc, qp);
	TASK_INIT(&qp->rxc_db_work, 0, ntb_transport_rxc_db, qp);

	STAILQ_INIT(&qp->rx_post_q);
	STAILQ_INIT(&qp->rx_pend_q);
	STAILQ_INIT(&qp->tx_free_q);

	callout_reset(&qp->link_work, 0, ntb_qp_link_work, qp);
}