Skip to content
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)
        }
      }
    }
  }
      

Clone this wiki locally