UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
1,311 Views
Registered: ‎03-28-2014

C2H Data is transfered to cyclic buffer but not copied to user space

I'm trying to transfer three 32K blocks of data from my FPGA to the host computer. The data is placed in the cyclic buffer correctly, but for some reason it is not all transferred to user space, which causes the receiver program to hang.

 

As you can see in my dmesg log below, engine_ring_process receives 32K in one burst and all of the data is processed correctly by complete_cyclic and copy_cyclic_to_user. However, when there are two bursts of 32K processed by engine_ring_process only the first 32K is copied to user space.

 

 

[ 3354.683302] engine_ring_process(): C2H0: result[engine->rx_tail=  0].status = 0x52b40000
[ 3354.683304] engine_ring_process(): C2H0: result[engine->rx_tail=  0].length = 4096
[ 3354.683306] engine_ring_process(): C2H0: result[engine->rx_tail=  1].status = 0x52b40000
[ 3354.683307] engine_ring_process(): C2H0: result[engine->rx_tail=  1].length = 4096
[ 3354.683307] engine_ring_process(): C2H0: result[engine->rx_tail=  2].status = 0x52b40000
[ 3354.683308] engine_ring_process(): C2H0: result[engine->rx_tail=  2].length = 4096
[ 3354.683309] engine_ring_process(): C2H0: result[engine->rx_tail=  3].status = 0x52b40000
[ 3354.683310] engine_ring_process(): C2H0: result[engine->rx_tail=  3].length = 4096
[ 3354.683311] engine_ring_process(): C2H0: result[engine->rx_tail=  4].status = 0x52b40000
[ 3354.683312] engine_ring_process(): C2H0: result[engine->rx_tail=  4].length = 4096
[ 3354.683313] engine_ring_process(): C2H0: result[engine->rx_tail=  5].status = 0x52b40000
[ 3354.683313] engine_ring_process(): C2H0: result[engine->rx_tail=  5].length = 4096
[ 3354.683314] engine_ring_process(): C2H0: result[engine->rx_tail=  6].status = 0x52b40000
[ 3354.683315] engine_ring_process(): C2H0: result[engine->rx_tail=  6].length = 4096
[ 3354.683316] engine_ring_process(): C2H0: result[engine->rx_tail=  7].status = 0x52b40001
[ 3354.683317] engine_ring_process(): C2H0: result[engine->rx_tail=  7].length = 4096
[ 3354.683319] complete_cyclic(): C2H0: result[engine->rx_head=  0].status = 0x52b40000
[ 3354.683320] complete_cyclic(): C2H0: result[engine->rx_head=  0].length = 4096
[ 3354.683321] complete_cyclic(): C2H0: pkt_length=4096 (no EOP yet)
[ 3354.683322] complete_cyclic(): C2H0: result[engine->rx_head=  1].status = 0x52b40000
[ 3354.683323] complete_cyclic(): C2H0: result[engine->rx_head=  1].length = 4096
[ 3354.683324] complete_cyclic(): C2H0: pkt_length=8192 (no EOP yet)
[ 3354.683325] complete_cyclic(): C2H0: result[engine->rx_head=  2].status = 0x52b40000
[ 3354.683326] complete_cyclic(): C2H0: result[engine->rx_head=  2].length = 4096
[ 3354.683326] complete_cyclic(): C2H0: pkt_length=12288 (no EOP yet)
[ 3354.683327] complete_cyclic(): C2H0: result[engine->rx_head=  3].status = 0x52b40000
[ 3354.683328] complete_cyclic(): C2H0: result[engine->rx_head=  3].length = 4096
[ 3354.683329] complete_cyclic(): C2H0: pkt_length=16384 (no EOP yet)
[ 3354.683330] complete_cyclic(): C2H0: result[engine->rx_head=  4].status = 0x52b40000
[ 3354.683331] complete_cyclic(): C2H0: result[engine->rx_head=  4].length = 4096
[ 3354.683331] complete_cyclic(): C2H0: pkt_length=20480 (no EOP yet)
[ 3354.683332] complete_cyclic(): C2H0: result[engine->rx_head=  5].status = 0x52b40000
[ 3354.683333] complete_cyclic(): C2H0: result[engine->rx_head=  5].length = 4096
[ 3354.683334] complete_cyclic(): C2H0: pkt_length=24576 (no EOP yet)
[ 3354.683335] complete_cyclic(): C2H0: result[engine->rx_head=  6].status = 0x52b40000
[ 3354.683336] complete_cyclic(): C2H0: result[engine->rx_head=  6].length = 4096
[ 3354.683336] complete_cyclic(): C2H0: pkt_length=28672 (no EOP yet)
[ 3354.683337] complete_cyclic(): C2H0: result[engine->rx_head=  7].status = 0x52b40001
[ 3354.683338] complete_cyclic(): C2H0: result[engine->rx_head=  7].length = 4096
[ 3354.683339] complete_cyclic(): C2H0: pkt_length=32768 (with EOP)
[ 3354.683340] copy_cyclic_to_user(): C2H0: head = 0, copy 4096 bytes from ffffc9000fed6000 to 0000000000a9f000
[ 3354.683343] copy_cyclic_to_user(): C2H0: head = 1, copy 4096 bytes from ffffc9000fed7000 to 0000000000aa0000
[ 3354.683345] copy_cyclic_to_user(): C2H0: head = 2, copy 4096 bytes from ffffc9000fed8000 to 0000000000aa1000
[ 3354.683347] copy_cyclic_to_user(): C2H0: head = 3, copy 4096 bytes from ffffc9000fed9000 to 0000000000aa2000
[ 3354.683349] copy_cyclic_to_user(): C2H0: head = 4, copy 4096 bytes from ffffc9000feda000 to 0000000000aa3000
[ 3354.683351] copy_cyclic_to_user(): C2H0: head = 5, copy 4096 bytes from ffffc9000fedb000 to 0000000000aa4000
[ 3354.683353] copy_cyclic_to_user(): C2H0: head = 6, copy 4096 bytes from ffffc9000fedc000 to 0000000000aa5000
[ 3354.683355] copy_cyclic_to_user(): C2H0: head = 7, copy 4096 bytes from ffffc9000fedd000 to 0000000000aa6000
[ 3354.683357] char_sgdma_read_cyclic(): C2H0: returning 32768
[ 3354.683624] char_sgdma_read_cyclic(): C2H0: char_sgdma_read_cyclic()
[ 3354.683627] engine_service_poll(): C2H0: Calling engine_service_cyclic() for C2H engine ffff882010b3b400
[ 3354.683628] engine_service_cyclic(): C2H0: engine_service_cyclic() here
[ 3354.683629] engine_ring_process(): C2H0: result[engine->rx_tail=  8].status = 0x52b40000
[ 3354.683630] engine_ring_process(): C2H0: result[engine->rx_tail=  8].length = 4096
[ 3354.683631] engine_ring_process(): C2H0: result[engine->rx_tail=  9].status = 0x52b40000
[ 3354.683632] engine_ring_process(): C2H0: result[engine->rx_tail=  9].length = 4096
[ 3354.683633] engine_ring_process(): C2H0: result[engine->rx_tail= 10].status = 0x52b40000
[ 3354.683634] engine_ring_process(): C2H0: result[engine->rx_tail= 10].length = 4096
[ 3354.683635] engine_ring_process(): C2H0: result[engine->rx_tail= 11].status = 0x52b40000
[ 3354.683636] engine_ring_process(): C2H0: result[engine->rx_tail= 11].length = 4096
[ 3354.683637] engine_ring_process(): C2H0: result[engine->rx_tail= 12].status = 0x52b40000
[ 3354.683638] engine_ring_process(): C2H0: result[engine->rx_tail= 12].length = 4096
[ 3354.683639] engine_ring_process(): C2H0: result[engine->rx_tail= 13].status = 0x52b40000
[ 3354.683640] engine_ring_process(): C2H0: result[engine->rx_tail= 13].length = 4096
[ 3354.683641] engine_ring_process(): C2H0: result[engine->rx_tail= 14].status = 0x52b40000
[ 3354.683642] engine_ring_process(): C2H0: result[engine->rx_tail= 14].length = 4096
[ 3354.683643] engine_ring_process(): C2H0: result[engine->rx_tail= 15].status = 0x52b40001
[ 3354.683643] engine_ring_process(): C2H0: result[engine->rx_tail= 15].length = 4096
[ 3354.683645] engine_ring_process(): C2H0: result[engine->rx_tail= 16].status = 0x52b40000
[ 3354.683645] engine_ring_process(): C2H0: result[engine->rx_tail= 16].length = 4096
[ 3354.683646] engine_ring_process(): C2H0: result[engine->rx_tail= 17].status = 0x52b40000
[ 3354.683647] engine_ring_process(): C2H0: result[engine->rx_tail= 17].length = 4096
[ 3354.683648] engine_ring_process(): C2H0: result[engine->rx_tail= 18].status = 0x52b40000
[ 3354.683649] engine_ring_process(): C2H0: result[engine->rx_tail= 18].length = 4096
[ 3354.683650] engine_ring_process(): C2H0: result[engine->rx_tail= 19].status = 0x52b40000
[ 3354.683651] engine_ring_process(): C2H0: result[engine->rx_tail= 19].length = 4096
[ 3354.683652] engine_ring_process(): C2H0: result[engine->rx_tail= 20].status = 0x52b40000
[ 3354.683652] engine_ring_process(): C2H0: result[engine->rx_tail= 20].length = 4096
[ 3354.683653] engine_ring_process(): C2H0: result[engine->rx_tail= 21].status = 0x52b40000
[ 3354.683654] engine_ring_process(): C2H0: result[engine->rx_tail= 21].length = 4096
[ 3354.683655] engine_ring_process(): C2H0: result[engine->rx_tail= 22].status = 0x52b40000
[ 3354.683656] engine_ring_process(): C2H0: result[engine->rx_tail= 22].length = 4096
[ 3354.683657] engine_ring_process(): C2H0: result[engine->rx_tail= 23].status = 0x52b40001
[ 3354.683658] engine_ring_process(): C2H0: result[engine->rx_tail= 23].length = 4096
[ 3354.683658] complete_cyclic(): C2H0: result[engine->rx_head=  8].status = 0x52b40000
[ 3354.683659] complete_cyclic(): C2H0: result[engine->rx_head=  8].length = 4096
[ 3354.683660] complete_cyclic(): C2H0: pkt_length=4096 (no EOP yet)
[ 3354.683661] complete_cyclic(): C2H0: result[engine->rx_head=  9].status = 0x52b40000
[ 3354.683662] complete_cyclic(): C2H0: result[engine->rx_head=  9].length = 4096
[ 3354.683663] complete_cyclic(): C2H0: pkt_length=8192 (no EOP yet)
[ 3354.683664] complete_cyclic(): C2H0: result[engine->rx_head= 10].status = 0x52b40000
[ 3354.683664] complete_cyclic(): C2H0: result[engine->rx_head= 10].length = 4096
[ 3354.683665] complete_cyclic(): C2H0: pkt_length=12288 (no EOP yet)
[ 3354.683666] complete_cyclic(): C2H0: result[engine->rx_head= 11].status = 0x52b40000
[ 3354.683667] complete_cyclic(): C2H0: result[engine->rx_head= 11].length = 4096
[ 3354.683668] complete_cyclic(): C2H0: pkt_length=16384 (no EOP yet)
[ 3354.683669] complete_cyclic(): C2H0: result[engine->rx_head= 12].status = 0x52b40000
[ 3354.683670] complete_cyclic(): C2H0: result[engine->rx_head= 12].length = 4096
[ 3354.683670] complete_cyclic(): C2H0: pkt_length=20480 (no EOP yet)
[ 3354.683671] complete_cyclic(): C2H0: result[engine->rx_head= 13].status = 0x52b40000
[ 3354.683672] complete_cyclic(): C2H0: result[engine->rx_head= 13].length = 4096
[ 3354.683673] complete_cyclic(): C2H0: pkt_length=24576 (no EOP yet)
[ 3354.683674] complete_cyclic(): C2H0: result[engine->rx_head= 14].status = 0x52b40000
[ 3354.683674] complete_cyclic(): C2H0: result[engine->rx_head= 14].length = 4096
[ 3354.683675] complete_cyclic(): C2H0: pkt_length=28672 (no EOP yet)
[ 3354.683676] complete_cyclic(): C2H0: result[engine->rx_head= 15].status = 0x52b40001
[ 3354.683677] complete_cyclic(): C2H0: result[engine->rx_head= 15].length = 4096
[ 3354.683678] complete_cyclic(): C2H0: pkt_length=32768 (with EOP)
[ 3354.683679] copy_cyclic_to_user(): C2H0: head = 8, copy 4096 bytes from ffffc9000fede000 to 0000000000a9f000
[ 3354.683680] copy_cyclic_to_user(): C2H0: head = 9, copy 4096 bytes from ffffc9000fedf000 to 0000000000aa0000
[ 3354.683682] copy_cyclic_to_user(): C2H0: head = 10, copy 4096 bytes from ffffc9000fee0000 to 0000000000aa1000
[ 3354.683683] copy_cyclic_to_user(): C2H0: head = 11, copy 4096 bytes from ffffc9000fee1000 to 0000000000aa2000
[ 3354.683685] copy_cyclic_to_user(): C2H0: head = 12, copy 4096 bytes from ffffc9000fee2000 to 0000000000aa3000
[ 3354.683686] copy_cyclic_to_user(): C2H0: head = 13, copy 4096 bytes from ffffc9000fee3000 to 0000000000aa4000
[ 3354.683687] copy_cyclic_to_user(): C2H0: head = 14, copy 4096 bytes from ffffc9000fee4000 to 0000000000aa5000
[ 3354.683688] copy_cyclic_to_user(): C2H0: head = 15, copy 4096 bytes from ffffc9000fee5000 to 0000000000aa6000
[ 3354.683689] char_sgdma_read_cyclic(): C2H0: returning 32768
[ 3354.683839] char_sgdma_read_cyclic(): C2H0: char_sgdma_read_cyclic()
[ 3354.683841] engine_service_poll(): C2H0: Calling engine_service_cyclic() for C2H engine ffff882010b3b400
[ 3354.683842] engine_service_cyclic(): C2H0: engine_service_cyclic() here

 

Tags (4)
0 Kudos
1 Reply
Adventurer
Adventurer
1,224 Views
Registered: ‎03-28-2014

Re: C2H Data is transfered to cyclic buffer but not copied to user space

The cause of this problem seems engine_service_cyclic_polled can process multiple packets per call, but complete_cyclic only processes one packet. Therefore, if engine_service_cyclic_polled has an eop_count > 1 then only one packet is processed before engine_service_cyclic_polled gets back into a look waiting for more data. If additional data is not transmitted, then engine_service_cyclic_polled never breaks out of its while loop and the remaining data is stuck in the cyclic buffer.

 

The following change causes engine_service_cyclic_polled to skip updating the tail pointer if all of the data from the previous update hasn't been processed yet. Note: eop_count has to be added to the engine structure and initialized to 0.

 

static int engine_service_cyclic_polled(struct xdma_engine *engine)
{
	int eop_count = engine->eop_count;
	int rc = 0;
	struct xdma_poll_wb *writeback_data;
	u32 sched_limit = 0;

	BUG_ON(!engine);
	BUG_ON(engine->magic != MAGIC_ENGINE);

	writeback_data = (struct xdma_poll_wb *)engine->poll_mode_addr_virt;

	while (eop_count == 0) {
		if (sched_limit != 0) {
			if ((sched_limit % NUM_POLLS_PER_SCHED) == 0)
				schedule();
		}
		sched_limit++;

		/* Monitor descriptor writeback address for errors */
		if ((writeback_data->completed_desc_count) & WB_ERR_MASK) {
			rc = -1;
			break;
		}

		eop_count = engine_ring_process(engine);
	}

	if (eop_count == 0) {
		engine_status_read(engine, 1);
		if ((engine->running) && !(engine->status & XDMA_STAT_BUSY)) {
			/* transfers on queue? */
			if (!list_empty(&engine->transfer_list))
				engine_transfer_dequeue(engine);

			engine_service_shutdown(engine);
		}
	}
	eop_count--;
	engine->eop_count = eop_count;
	return rc;
}