|
@@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
|
uint32_t wptr, rptr;
|
|
uint32_t wptr, rptr;
|
|
unsigned int *queue_address;
|
|
unsigned int *queue_address;
|
|
|
|
|
|
|
|
+ /* When rptr == wptr, the buffer is empty.
|
|
|
|
+ * When rptr == wptr + 1, the buffer is full.
|
|
|
|
+ * It is always rptr that advances to the position of wptr, rather than
|
|
|
|
+ * the opposite. So we can only use up to queue_size_dwords - 1 dwords.
|
|
|
|
+ */
|
|
rptr = *kq->rptr_kernel;
|
|
rptr = *kq->rptr_kernel;
|
|
wptr = *kq->wptr_kernel;
|
|
wptr = *kq->wptr_kernel;
|
|
queue_address = (unsigned int *)kq->pq_kernel_addr;
|
|
queue_address = (unsigned int *)kq->pq_kernel_addr;
|
|
@@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
|
pr_debug("wptr: %d\n", wptr);
|
|
pr_debug("wptr: %d\n", wptr);
|
|
pr_debug("queue_address 0x%p\n", queue_address);
|
|
pr_debug("queue_address 0x%p\n", queue_address);
|
|
|
|
|
|
- available_size = (rptr - 1 - wptr + queue_size_dwords) %
|
|
|
|
|
|
+ available_size = (rptr + queue_size_dwords - 1 - wptr) %
|
|
queue_size_dwords;
|
|
queue_size_dwords;
|
|
|
|
|
|
- if (packet_size_in_dwords >= queue_size_dwords ||
|
|
|
|
- packet_size_in_dwords >= available_size) {
|
|
|
|
|
|
+ if (packet_size_in_dwords > available_size) {
|
|
/*
|
|
/*
|
|
* make sure calling functions know
|
|
* make sure calling functions know
|
|
* acquire_packet_buffer() failed
|
|
* acquire_packet_buffer() failed
|
|
@@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
|
}
|
|
}
|
|
|
|
|
|
if (wptr + packet_size_in_dwords >= queue_size_dwords) {
|
|
if (wptr + packet_size_in_dwords >= queue_size_dwords) {
|
|
|
|
+ /* make sure after rolling back to position 0, there is
|
|
|
|
+ * still enough space.
|
|
|
|
+ */
|
|
|
|
+ if (packet_size_in_dwords >= rptr) {
|
|
|
|
+ *buffer_ptr = NULL;
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ /* fill nops, roll back and start at position 0 */
|
|
while (wptr > 0) {
|
|
while (wptr > 0) {
|
|
queue_address[wptr] = kq->nop_packet;
|
|
queue_address[wptr] = kq->nop_packet;
|
|
wptr = (wptr + 1) % queue_size_dwords;
|
|
wptr = (wptr + 1) % queue_size_dwords;
|