|
|
1.1 root 1: DMA enqueue race condition handling
2:
3: hw_next_desc = nextDescriptor hw register
4: hw_curr_desc = currentDescriptor hw register
5: count_reg = 'Count' hw register
6: frame_queue = queue of kern_dma_frame_t (one per channel)
7: desc_queue = queue of kern_dma_desc_t's (one per dma_frame_t)
8: last_frame = end of frame_queue
9: last_desc = end of last_frame's desc_queue
10:
11: enqueue new_frame
12: {
13:
14: save current last_desc in old_tail;
15: create chain for new_frame;
16: link new_frame's chain onto old_tail;
17: link new_frame onto frame_queue;
18: if(hw_next_desc != NULL)
19: done;
20: else one of three cases:
21: 1. Missed update, channel still working on old_tail.
22: 2. Missed update, channel stopped.
23: 3. Update OK, channel working on new last_frame from
24: (new_frame).
25: if(hw_curr_desc != old_tail)
26: return OK - case 3;
27:
28: /*
29: * try to catch update in h/w.
30: */
31: hw_next_desc = new_frame;
32:
33: /*
34: * reading count register guarantees we avoid this race condition:
35: *
36: * -- TE finishes last desc, next_descriptor null, sends "clear
37: * descriptorListNotEmpty" packet to device.
38: * -- Kernel reads descriptorListNotEmpty, it's still 1 because the
39: * packet just sent to the device is NOT atomic and can be
40: * interrupted by a kernel access (ONCE).
41: * Thus reading count does two things:
42: * -- guarantees that descriptorListNotEmpty will be valid
43: * (i.e., 0) when kernel reads it in case of underrun, and
44: * -- also tells kernel than channel is OK (running) if count is
45: * non-zero, since TE clears it before sending the "clear
46: * descriptorListNotEmpty" packet to the device.
47: */
48: if((count != 0) || channel's descriptorListNotEmpty)
49: return OK - case 1, did h/w update in time;
50: if(hw_curr_desc == new last_desc)
51: return OK - h/w update in time, and new_frame is already done
52:
53: /*
54: * case 3. Return error and prepare channel for restart.
55: */
56: hw_curr_desc = new_frame;
57: return(missed error);
58: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.