forked from NetFPGA-NewNIC/linux-driver
-
Notifications
You must be signed in to change notification settings - Fork 1
rx algorithm
hwanju edited this page Nov 24, 2014
·
17 revisions
func get_lbuf_status():
lbuf_status = get_first_qword() /* atomically read qword */
nr_dwords = get_lo_dword(lbuf_status) << 1 /* nr_qwords to nr_dwords */
is_closed = get_hi_dword(lbuf_status) & 0x1 /* lowest bit */
return (nr_dwords, is_closed)
global rx_dword_offset /* this should be managed in adapter struct */
func rx_loop_per_lbuf():
while (end_of_lbuf() == false) {
cur_pkt_len = get_pkt_len(rx_dword_offset)
if (cur_pkt_len == 0) {
/* check if lbuf is closed:
this check is needed if for the previous packet timeout occurs, but still not closed.
In this case, next_pkt_len could be 0 and next loop stops polling because cur_pkt_len == 0.
When this driver wakes up by IRQ, the device could close this lbuf, since the coming packet
doesn't fit in the remaining space in the current lbuf */
nr_dwords, is_closed = get_lbuf_status()
if (nr_dwords == next_dword_offset && is_closed == 1) {
switch_to_next_lbuf() /* it changes current lbuf and resets rx_dword_offset */
break /* stop polling here */
}
/* Now, current packet hasn't even started to be received by host. */
/* if needed to wait for some time, keep polling..
interrupt can be raised earlier than even the packet hasn't started to be received
BUT, how to handle tx or spurious interrupts... */
if (need_to_wait())
continue
else
break
}
/* Now we have cur_pkt_len > 0, which means rx is started
it's time to poll next_pkt_len to know if rx is finished */
next_dword_offset = get_next_offset(rx_dword_offset, cur_pkt_len)
next_pkt_len = get_pkt_len(next_dword_offset)
if (next_pkt_len > 0) { /* rx is finished, so consume it and move forward */
consume_pkt(rx_dword_offset)
rx_dword_offset = next_dword_offset
}
else {
/* next_pkt_len == 0:
i) rx is not finished
ii) rx is finished, but
a) timeout -> next_pkt_len must adjusted to next 128B-aligned addr
b) closed -> current lbuf is closed, so no more packet will arrive here
*/
nr_dwords, is_closed = get_lbuf_status()
if (nr_dwords < next_dword_offset) {
/* i) case:
since current packet has already started to be received,
we can expect to receive it soon, so keep polling on next_pkt_len
*/
}
else { /* nr_dwords >= next_dword_offset */
/* ii) case */
consume_pkt(rx_dword_offset)
nr_dwords, is_closed = get_lbuf_status()
if (nr_dwords == next_dword_offset && is_closed == 1) {
/* ii.a case */
switch_to_next_lbuf() /* it changes current lbuf and resets rx_dword_offset */
break /* stop polling here */
}
/* ii.b case: here, nr_dowrds >= next_dword_offset,
should check where the next packet is placed once more, since HW could have
moved forward with more than one packet and timeout has occurred for a later one */
next_pkt_len = get_pkt_len(next_dword_offset)
if (next_pkt_len == 0) {
/* this packet experienced timeout, so jump to next 128B-aligned offset */
rx_dword_offset = get_128B_aligned(next_dword_offset)
}
}
}
}