bzr branch
http://suren.me/webbzr/alps/pcitool
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
1 |
#define NWL_RING_GET(data, offset) *(uint32_t*)(((char*)(data)) + (offset))
|
2 |
#define NWL_RING_SET(data, offset, val) *(uint32_t*)(((char*)(data)) + (offset)) = (val)
|
|
3 |
#define NWL_RING_UPDATE(data, offset, mask, val) *(uint32_t*)(((char*)(data)) + (offset)) = ((*(uint32_t*)(((char*)(data)) + (offset)))&(mask))|(val)
|
|
4 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
5 |
static int dma_nwl_compute_read_s2c_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, unsigned char *ring, uint32_t ring_pa) { |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
6 |
uint32_t val; |
7 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
8 |
const char *base = ectx->base_addr; |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
9 |
|
10 |
nwl_read_register(val, ctx, base, REG_SW_NEXT_BD); |
|
11 |
if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { |
|
76
by Suren A. Chilingaryan
Handle correctly reference counting in the driver |
12 |
if (val < ring_pa) pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%lx) is below start of ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
13 |
else pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
14 |
return PCILIB_ERROR_INVALID_STATE; |
15 |
}
|
|
16 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
17 |
ectx->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
18 |
if (ectx->head >= PCILIB_NWL_DMA_PAGES) { |
|
19 |
pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", ectx->head); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
20 |
return PCILIB_ERROR_INVALID_STATE; |
21 |
}
|
|
22 |
||
23 |
nwl_read_register(val, ctx, base, REG_DMA_ENG_NEXT_BD); |
|
24 |
if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { |
|
76
by Suren A. Chilingaryan
Handle correctly reference counting in the driver |
25 |
if (val < ring_pa) pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%lx) is below start of ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
26 |
else pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
27 |
return PCILIB_ERROR_INVALID_STATE; |
28 |
}
|
|
29 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
30 |
ectx->tail = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
31 |
if (ectx->tail >= PCILIB_NWL_DMA_PAGES) { |
|
32 |
pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu) out of range)", ectx->tail); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
33 |
return PCILIB_ERROR_INVALID_STATE; |
34 |
}
|
|
78
by Suren A. Chilingaryan
Correctly detect the tail pointer of C2S ring |
35 |
|
250
by Suren A. Chilingaryan
Provide an interface for logging debug messages |
36 |
pcilib_debug(DMA, "S2C: %lu %lu\n", ectx->tail, ectx->head); |
78
by Suren A. Chilingaryan
Correctly detect the tail pointer of C2S ring |
37 |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
38 |
return 0; |
39 |
}
|
|
40 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
41 |
static int dma_nwl_compute_read_c2s_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, unsigned char *ring, uint32_t ring_pa) { |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
42 |
uint32_t val; |
43 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
44 |
const char *base = ectx->base_addr; |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
45 |
|
46 |
nwl_read_register(val, ctx, base, REG_SW_NEXT_BD); |
|
47 |
if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { |
|
76
by Suren A. Chilingaryan
Handle correctly reference counting in the driver |
48 |
if (val < ring_pa) pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%lx) is below start of the ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
49 |
else pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
50 |
return PCILIB_ERROR_INVALID_STATE; |
51 |
}
|
|
52 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
53 |
ectx->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
54 |
if (ectx->head >= PCILIB_NWL_DMA_PAGES) { |
|
55 |
pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", ectx->head); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
56 |
return PCILIB_ERROR_INVALID_STATE; |
57 |
}
|
|
58 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
59 |
ectx->tail = ectx->head + 1; |
60 |
if (ectx->tail == PCILIB_NWL_DMA_PAGES) ectx->tail = 0; |
|
78
by Suren A. Chilingaryan
Correctly detect the tail pointer of C2S ring |
61 |
|
250
by Suren A. Chilingaryan
Provide an interface for logging debug messages |
62 |
pcilib_debug(DMA, "C2S: %lu %lu\n", ectx->tail, ectx->head); |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
63 |
|
64 |
return 0; |
|
65 |
}
|
|
66 |
||
67 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
68 |
static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
69 |
int err = 0; |
70 |
||
71 |
int i; |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
72 |
int preserve = 0; |
71
by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions |
73 |
uint16_t sub_use; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
74 |
uint32_t val; |
75 |
uint32_t buf_sz; |
|
76 |
uint64_t buf_pa; |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
77 |
pcilib_kmem_reuse_state_t reuse_ring, reuse_pages; |
73
by Suren A. Chilingaryan
Implement DMA access synchronization in the driver |
78 |
pcilib_kmem_flags_t flags; |
105
by Suren A. Chilingaryan
Properly perform synchronization of DMA buffers |
79 |
pcilib_kmem_type_t type; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
80 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
81 |
char *base = ectx->base_addr; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
82 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
83 |
if (ectx->pages) return 0; |
75
by Suren A. Chilingaryan
Few fixes |
84 |
|
71
by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions |
85 |
// Or bidirectional specified by 0x0|addr, or read 0x0|addr and write 0x80|addr
|
236
by Suren A. Chilingaryan
Big redign of model structures |
86 |
type = (ectx->desc->direction == PCILIB_DMA_TO_DEVICE)?PCILIB_KMEM_TYPE_DMA_S2C_PAGE:PCILIB_KMEM_TYPE_DMA_C2S_PAGE; |
87 |
sub_use = ectx->desc->addr|((ectx->desc->direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00); |
|
88 |
flags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ectx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0); |
|
75
by Suren A. Chilingaryan
Few fixes |
89 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
90 |
pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, sub_use), flags); |
91 |
pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, type, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, sub_use), flags); |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
92 |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
93 |
if (!ring||!pages) { |
236
by Suren A. Chilingaryan
Big redign of model structures |
94 |
if (pages) pcilib_free_kernel_memory(ctx->dmactx.pcilib, pages, 0); |
95 |
if (ring) pcilib_free_kernel_memory(ctx->dmactx.pcilib, ring, 0); |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
96 |
return PCILIB_ERROR_MEMORY; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
97 |
}
|
71
by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions |
98 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
99 |
reuse_ring = pcilib_kmem_is_reused(ctx->dmactx.pcilib, ring); |
100 |
reuse_pages = pcilib_kmem_is_reused(ctx->dmactx.pcilib, pages); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
101 |
|
181
by Suren A. Chilingaryan
Fixes 2 bugs in NWL DMA initalization: DMA engine was not restarted in case of incosistency leading to possibility of data loss on DMA; Persistent mode was not respected after re-initalization (stop/start dma) |
102 |
// I guess idea here was that we not need to check all that stuff during the second iteration
|
103 |
// which is basicaly true (shall we expect any driver-triggered changes or parallel accesses?)
|
|
104 |
// but still we need to set preserve flag (and that if we enforcing preservation --start-dma).
|
|
105 |
// Probably having checks anyway is not harming...
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
106 |
// if (!ectx->preserve) {
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
107 |
if (reuse_ring == reuse_pages) { |
108 |
if (reuse_ring & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing..."); |
|
109 |
else if (reuse_ring & PCILIB_KMEM_REUSE_REUSED) { |
|
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
110 |
if ((reuse_ring & PCILIB_KMEM_REUSE_PERSISTENT) == 0) pcilib_warning("Lost DMA buffers are found (non-persistent mode), reinitializing..."); |
111 |
else if ((reuse_ring & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing..."); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
112 |
else { |
236
by Suren A. Chilingaryan
Big redign of model structures |
113 |
nwl_read_register(val, ctx, ectx->base_addr, REG_DMA_ENG_CTRL_STATUS); |
79
by Suren A. Chilingaryan
Few more fixes |
114 |
|
83
by Suren A. Chilingaryan
Correctly check if DMA is already enabled |
115 |
if ((val&DMA_ENG_RUNNING) == 0) pcilib_warning("Lost DMA buffers are found (DMA engine is stopped), reinitializing..."); |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
116 |
else preserve = 1; |
117 |
}
|
|
118 |
}
|
|
119 |
} else pcilib_warning("Inconsistent DMA buffers (modes of ring and page buffers does not match), reinitializing...."); |
|
181
by Suren A. Chilingaryan
Fixes 2 bugs in NWL DMA initalization: DMA engine was not restarted in case of incosistency leading to possibility of data loss on DMA; Persistent mode was not respected after re-initalization (stop/start dma) |
120 |
// }
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
121 |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
122 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
123 |
unsigned char *data = (unsigned char*)pcilib_kmem_get_ua(ctx->dmactx.pcilib, ring); |
352.1.4
by Suren A. Chilingaryan
Distinguish between hardware and bus addresses in pcilib |
124 |
uint32_t ring_pa = pcilib_kmem_get_ba(ctx->dmactx.pcilib, ring); |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
125 |
|
126 |
if (preserve) { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
127 |
if (ectx->desc->direction == PCILIB_DMA_FROM_DEVICE) err = dma_nwl_compute_read_c2s_pointers(ctx, ectx, data, ring_pa); |
128 |
else err = dma_nwl_compute_read_s2c_pointers(ctx, ectx, data, ring_pa); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
129 |
|
130 |
if (err) preserve = 0; |
|
131 |
}
|
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
132 |
|
79
by Suren A. Chilingaryan
Few more fixes |
133 |
if (preserve) { |
236
by Suren A. Chilingaryan
Big redign of model structures |
134 |
ectx->reused = 1; |
135 |
buf_sz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, pages, 0); |
|
79
by Suren A. Chilingaryan
Few more fixes |
136 |
} else { |
236
by Suren A. Chilingaryan
Big redign of model structures |
137 |
ectx->reused = 0; |
181
by Suren A. Chilingaryan
Fixes 2 bugs in NWL DMA initalization: DMA engine was not restarted in case of incosistency leading to possibility of data loss on DMA; Persistent mode was not respected after re-initalization (stop/start dma) |
138 |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
139 |
memset(data, 0, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
140 |
||
141 |
for (i = 0; i < PCILIB_NWL_DMA_PAGES; i++, data += PCILIB_NWL_DMA_DESCRIPTOR_SIZE) { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
142 |
buf_pa = pcilib_kmem_get_block_pa(ctx->dmactx.pcilib, pages, i); |
143 |
buf_sz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, pages, i); |
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
144 |
|
145 |
NWL_RING_SET(data, DMA_BD_NDESC_OFFSET, ring_pa + ((i + 1) % PCILIB_NWL_DMA_PAGES) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE); |
|
146 |
NWL_RING_SET(data, DMA_BD_BUFAL_OFFSET, buf_pa&0xFFFFFFFF); |
|
147 |
NWL_RING_SET(data, DMA_BD_BUFAH_OFFSET, buf_pa>>32); |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
148 |
#ifdef NWL_GENERATE_DMA_IRQ
|
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
149 |
NWL_RING_SET(data, DMA_BD_BUFL_CTRL_OFFSET, buf_sz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
150 |
#else /* NWL_GENERATE_DMA_IRQ */ |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
151 |
NWL_RING_SET(data, DMA_BD_BUFL_CTRL_OFFSET, buf_sz); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
152 |
#endif /* NWL_GENERATE_DMA_IRQ */ |
74
by Suren A. Chilingaryan
Implement DMA access synchronization for NWL implementation |
153 |
}
|
154 |
||
155 |
val = ring_pa; |
|
156 |
nwl_write_register(val, ctx, base, REG_DMA_ENG_NEXT_BD); |
|
157 |
nwl_write_register(val, ctx, base, REG_SW_NEXT_BD); |
|
158 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
159 |
ectx->head = 0; |
160 |
ectx->tail = 0; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
161 |
}
|
162 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
163 |
ectx->ring = ring; |
164 |
ectx->pages = pages; |
|
165 |
ectx->page_size = buf_sz; |
|
166 |
ectx->ring_size = PCILIB_NWL_DMA_PAGES; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
167 |
|
168 |
return 0; |
|
169 |
}
|
|
170 |
||
171 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
172 |
static size_t dma_nwl_clean_buffers(nwl_dma_t * ctx, pcilib_nwl_engine_context_t *ectx) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
173 |
size_t res = 0; |
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
174 |
uint32_t status; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
175 |
|
370
by Suren A. Chilingaryan
RPM generation |
176 |
volatile unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring); |
236
by Suren A. Chilingaryan
Big redign of model structures |
177 |
ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
178 |
|
179 |
next_buffer: |
|
180 |
status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_STATUS_MASK; |
|
181 |
// control = NWL_RING_GET(ring, DMA_BD_BUFL_CTRL_OFFSET)&DMA_BD_CTRL_MASK;
|
|
182 |
||
183 |
if (status & DMA_BD_ERROR_MASK) { |
|
184 |
pcilib_error("NWL DMA Engine reported error in ring descriptor"); |
|
185 |
return (size_t)-1; |
|
186 |
}
|
|
187 |
||
188 |
if (status & DMA_BD_SHORT_MASK) { |
|
189 |
pcilib_error("NWL DMA Engine reported short error"); |
|
190 |
return (size_t)-1; |
|
191 |
}
|
|
192 |
||
193 |
if (status & DMA_BD_COMP_MASK) { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
194 |
ectx->tail++; |
195 |
if (ectx->tail == ectx->ring_size) { |
|
196 |
ring -= (ectx->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
|
197 |
ectx->tail = 0; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
198 |
} else { |
199 |
ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
|
200 |
}
|
|
201 |
||
202 |
res++; |
|
203 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
204 |
if (ectx->tail != ectx->head) goto next_buffer; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
205 |
}
|
206 |
||
207 |
// printf("====> Cleaned: %i\n", res);
|
|
208 |
return res; |
|
209 |
}
|
|
210 |
||
211 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
212 |
static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_context_t *ectx, size_t n_buffers, pcilib_timeout_t timeout) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
213 |
struct timeval start, cur; |
214 |
||
215 |
size_t res, n = 0; |
|
216 |
size_t head; |
|
217 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
218 |
for (head = ectx->head; (((head + 1)%ectx->ring_size) != ectx->tail)&&(n < n_buffers); head++, n++); |
219 |
if (n == n_buffers) return ectx->head; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
220 |
|
221 |
gettimeofday(&start, NULL); |
|
222 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
223 |
res = dma_nwl_clean_buffers(ctx, ectx); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
224 |
if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID; |
225 |
else n += res; |
|
226 |
||
227 |
||
228 |
while (n < n_buffers) { |
|
229 |
if (timeout != PCILIB_TIMEOUT_INFINITE) { |
|
230 |
gettimeofday(&cur, NULL); |
|
231 |
if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > timeout) break; |
|
232 |
}
|
|
233 |
||
234 |
usleep (10); |
|
235 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
236 |
res = dma_nwl_clean_buffers(ctx, ectx); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
237 |
if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID; |
238 |
else if (res > 0) { |
|
239 |
gettimeofday(&start, NULL); |
|
240 |
n += res; |
|
241 |
}
|
|
242 |
}
|
|
79
by Suren A. Chilingaryan
Few more fixes |
243 |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
244 |
if (n < n_buffers) return PCILIB_DMA_BUFFER_INVALID; |
245 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
246 |
return ectx->head; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
247 |
}
|
248 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
249 |
static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, size_t size, int eop, pcilib_timeout_t timeout) { |
66
by Suren A. Chilingaryan
Few fixes |
250 |
int flags = 0; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
251 |
|
252 |
uint32_t val; |
|
370
by Suren A. Chilingaryan
RPM generation |
253 |
volatile unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring); |
352.1.4
by Suren A. Chilingaryan
Distinguish between hardware and bus addresses in pcilib |
254 |
uint32_t ring_pa = pcilib_kmem_get_ba(ctx->dmactx.pcilib, ectx->ring); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
255 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
256 |
ring += ectx->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
257 |
|
258 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
259 |
if (!ectx->writting) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
260 |
flags |= DMA_BD_SOP_MASK; |
236
by Suren A. Chilingaryan
Big redign of model structures |
261 |
ectx->writting = 1; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
262 |
}
|
263 |
if (eop) { |
|
264 |
flags |= DMA_BD_EOP_MASK; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
265 |
ectx->writting = 0; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
266 |
}
|
79
by Suren A. Chilingaryan
Few more fixes |
267 |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
268 |
NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, size|flags); |
269 |
NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, size); |
|
270 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
271 |
ectx->head++; |
272 |
if (ectx->head == ectx->ring_size) ectx->head = 0; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
273 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
274 |
val = ring_pa + ectx->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
275 |
nwl_write_register(val, ctx, ectx->base_addr, REG_SW_NEXT_BD); |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
276 |
|
277 |
return 0; |
|
278 |
}
|
|
279 |
||
280 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
281 |
static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, size_t *size, int *eop, pcilib_timeout_t timeout) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
282 |
struct timeval start, cur; |
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
283 |
uint32_t status_size, status; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
284 |
|
370
by Suren A. Chilingaryan
RPM generation |
285 |
volatile unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
286 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
287 |
ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
288 |
|
289 |
gettimeofday(&start, NULL); |
|
290 |
||
291 |
do { |
|
292 |
status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); |
|
293 |
status = status_size & DMA_BD_STATUS_MASK; |
|
294 |
||
295 |
if (status & DMA_BD_ERROR_MASK) { |
|
296 |
pcilib_error("NWL DMA Engine reported error in ring descriptor"); |
|
297 |
return (size_t)-1; |
|
298 |
}
|
|
299 |
||
300 |
if (status & DMA_BD_COMP_MASK) { |
|
301 |
if (status & DMA_BD_EOP_MASK) *eop = 1; |
|
302 |
else *eop = 0; |
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
303 |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
304 |
*size = status_size & DMA_BD_BUFL_MASK; |
109
by Suren A. Chilingaryan
Improvements of DMA engine |
305 |
|
306 |
/*
|
|
307 |
if (mrd) {
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
308 |
if ((ectx->tail + 1) == ectx->ring_size) ring -= ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
309 |
else ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
|
310 |
*mrd = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_COMP_MASK;
|
|
311 |
}
|
|
312 |
*/
|
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
313 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
314 |
return ectx->tail; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
315 |
}
|
316 |
||
317 |
usleep(10); |
|
318 |
gettimeofday(&cur, NULL); |
|
319 |
} while ((timeout == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < timeout)); |
|
320 |
||
321 |
return (size_t)-1; |
|
322 |
}
|
|
323 |
||
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
324 |
/*
|
325 |
// This function is not used now, but we may need it in the future
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
326 |
static int dma_nwl_is_overflown(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) {
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
327 |
uint32_t status;
|
236
by Suren A. Chilingaryan
Big redign of model structures |
328 |
unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
|
329 |
if (ectx->tail > 0) ring += (ectx->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
|
|
330 |
else ring += (ectx->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
|
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
331 |
|
332 |
status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
|
|
333 |
return status&DMA_BD_COMP_MASK?1:0;
|
|
334 |
}
|
|
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
335 |
*/
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
336 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
337 |
static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) { |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
338 |
uint32_t val; |
339 |
||
370
by Suren A. Chilingaryan
RPM generation |
340 |
volatile unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring); |
352.1.4
by Suren A. Chilingaryan
Distinguish between hardware and bus addresses in pcilib |
341 |
uint32_t ring_pa = pcilib_kmem_get_ba(ctx->dmactx.pcilib, ectx->ring); |
236
by Suren A. Chilingaryan
Big redign of model structures |
342 |
size_t bufsz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, ectx->pages, ectx->tail); |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
343 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
344 |
ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
345 |
|
346 |
#ifdef NWL_GENERATE_DMA_IRQ
|
|
347 |
NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK); |
|
348 |
#else /* NWL_GENERATE_DMA_IRQ */ |
|
349 |
NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz); |
|
350 |
#endif /* NWL_GENERATE_DMA_IRQ */ |
|
351 |
||
352 |
NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, 0); |
|
353 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
354 |
val = ring_pa + ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
355 |
nwl_write_register(val, ctx, ectx->base_addr, REG_SW_NEXT_BD); |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
356 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
357 |
ectx->tail++; |
358 |
if (ectx->tail == ectx->ring_size) ectx->tail = 0; |
|
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
359 |
|
360 |
return 0; |
|
58
by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes |
361 |
}
|
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
362 |
|
109
by Suren A. Chilingaryan
Improvements of DMA engine |
363 |
int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) { |
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
364 |
size_t i; |
104
by Suren A. Chilingaryan
Precisely estimate used buffers for C2S engines |
365 |
uint32_t bstatus; |
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
366 |
nwl_dma_t *ctx = (nwl_dma_t*)vctx; |
236
by Suren A. Chilingaryan
Big redign of model structures |
367 |
pcilib_nwl_engine_context_t *ectx = ctx->engines + dma; |
368 |
unsigned char *ring = (unsigned char*)pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring); |
|
104
by Suren A. Chilingaryan
Precisely estimate used buffers for C2S engines |
369 |
|
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
370 |
|
371 |
if (!status) return -1; |
|
372 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
373 |
status->started = ectx->started; |
374 |
status->ring_size = ectx->ring_size; |
|
375 |
status->buffer_size = ectx->page_size; |
|
376 |
status->ring_tail = ectx->tail; |
|
265
by Suren A. Chilingaryan
Add fields reporting consumed buffers and space to the dma_engine_status and provide better ipedma benchmarking |
377 |
status->written_buffers = 0; |
378 |
status->written_bytes = 0; |
|
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
379 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
380 |
if (ectx->desc->direction == PCILIB_DMA_FROM_DEVICE) { |
126
by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization |
381 |
size_t pos = 0; |
236
by Suren A. Chilingaryan
Big redign of model structures |
382 |
for (i = 0; i < ectx->ring_size; i++) { |
104
by Suren A. Chilingaryan
Precisely estimate used buffers for C2S engines |
383 |
pos = status->ring_tail + i; |
236
by Suren A. Chilingaryan
Big redign of model structures |
384 |
if (pos >= ectx->ring_size) pos -= ectx->ring_size; |
104
by Suren A. Chilingaryan
Precisely estimate used buffers for C2S engines |
385 |
|
386 |
bstatus = NWL_RING_GET(ring + pos * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, DMA_BD_BUFL_STATUS_OFFSET); |
|
387 |
if ((bstatus&(DMA_BD_ERROR_MASK|DMA_BD_COMP_MASK)) == 0) break; |
|
388 |
}
|
|
389 |
status->ring_head = pos; |
|
390 |
} else { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
391 |
status->ring_head = ectx->head; |
104
by Suren A. Chilingaryan
Precisely estimate used buffers for C2S engines |
392 |
}
|
393 |
||
394 |
||
395 |
if (buffers) { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
396 |
for (i = 0; (i < ectx->ring_size)&&(i < n_buffers); i++) { |
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
397 |
bstatus = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); |
398 |
||
399 |
buffers[i].error = bstatus & (DMA_BD_ERROR_MASK/*|DMA_BD_SHORT_MASK*/); |
|
400 |
buffers[i].used = bstatus & DMA_BD_COMP_MASK; |
|
401 |
buffers[i].size = bstatus & DMA_BD_BUFL_MASK; |
|
402 |
buffers[i].first = bstatus & DMA_BD_SOP_MASK; |
|
403 |
buffers[i].last = bstatus & DMA_BD_EOP_MASK; |
|
404 |
||
405 |
ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE; |
|
406 |
}
|
|
265
by Suren A. Chilingaryan
Add fields reporting consumed buffers and space to the dma_engine_status and provide better ipedma benchmarking |
407 |
}
|
408 |
||
409 |
for (i = 0; (i < ectx->ring_size)&&(i < n_buffers); i++) { |
|
410 |
bstatus = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET); |
|
411 |
if (bstatus & DMA_BD_COMP_MASK) { |
|
412 |
status->written_buffers++; |
|
413 |
if ((bstatus & (DMA_BD_ERROR_MASK)) == 0) |
|
414 |
status->written_bytes += bstatus & DMA_BD_BUFL_MASK; |
|
415 |
}
|
|
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
416 |
}
|
265
by Suren A. Chilingaryan
Add fields reporting consumed buffers and space to the dma_engine_status and provide better ipedma benchmarking |
417 |
|
103
by Suren A. Chilingaryan
Provide information about active DMA engines & buffers |
418 |
return 0; |
419 |
}
|