virtio: Rework queue_dequeue to return a boolean.

It previously returned the cookie directly, which made it impossible
to distinguish between a NULL cookie and the function not having
anything to dequeue. This lead to some code setting a cookie that was
not actually used.

Return the dequeue status as a boolean and provide the cookie with an
optionally handed in pointer instead and adjust all users.

Change-Id: Iaac1726ac4bc7ae42bb96b8f0915852b6def5822
Reviewed-on: https://review.haiku-os.org/c/haiku/+/1814
Reviewed-by: Jérôme Duval <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Michael Lotz
2019-09-02 14:30:29 +00:00
committed by waddlesplash
parent 26c0b5e701
commit 9a2911ca8c
9 changed files with 38 additions and 45 deletions
+2 -1
View File
@@ -134,7 +134,8 @@ typedef struct {
uint16 (*queue_size)(virtio_queue queue); uint16 (*queue_size)(virtio_queue queue);
void* (*queue_dequeue)(virtio_queue queue, uint32* _usedLength); bool (*queue_dequeue)(virtio_queue queue, void** _cookie,
uint32* _usedLength);
} virtio_device_interface; } virtio_device_interface;
@@ -188,14 +188,13 @@ VirtioBalloonDevice::_Thread()
// alloc or release // alloc or release
TRACE("queue request\n"); TRACE("queue request\n");
status_t result = fVirtio->queue_request(queue, &fEntry, NULL, status_t result = fVirtio->queue_request(queue, &fEntry, NULL, NULL);
queue);
if (result != B_OK) { if (result != B_OK) {
ERROR("queueing failed (%s)\n", strerror(result)); ERROR("queueing failed (%s)\n", strerror(result));
return result; return result;
} }
while (fVirtio->queue_dequeue(queue, NULL) == NULL) { while (!fVirtio->queue_dequeue(queue, NULL, NULL)) {
TRACE("wait for response\n"); TRACE("wait for response\n");
queueConditionEntry.Wait(B_CAN_INTERRUPT); queueConditionEntry.Wait(B_CAN_INTERRUPT);
} }
@@ -184,11 +184,11 @@ virtio_queue_size(virtio_queue _queue)
} }
void* bool
virtio_queue_dequeue(virtio_queue _queue, uint32* _usedLength) virtio_queue_dequeue(virtio_queue _queue, void** _cookie, uint32* _usedLength)
{ {
VirtioQueue *queue = (VirtioQueue *)_queue; VirtioQueue *queue = (VirtioQueue *)_queue;
return queue->Dequeue(_usedLength); return queue->Dequeue(_cookie, _usedLength);
} }
@@ -131,7 +131,8 @@ public:
void EnableInterrupt(); void EnableInterrupt();
void DisableInterrupt(); void DisableInterrupt();
void* Dequeue(uint32* _usedLength = NULL); bool Dequeue(void** _cookie = NULL,
uint32* _usedLength = NULL);
private: private:
void UpdateAvailable(uint16 index); void UpdateAvailable(uint16 index);
@@ -245,13 +245,13 @@ VirtioQueue::Interrupt()
} }
void* bool
VirtioQueue::Dequeue(uint32* _usedLength) VirtioQueue::Dequeue(void** _cookie, uint32* _usedLength)
{ {
TRACE("Dequeue() fRingUsedIndex: %u\n", fRingUsedIndex); TRACE("Dequeue() fRingUsedIndex: %u\n", fRingUsedIndex);
if (fRingUsedIndex == fRing.used->idx) if (fRingUsedIndex == fRing.used->idx)
return NULL; return false;
uint16 usedIndex = fRingUsedIndex++ & (fRingSize - 1); uint16 usedIndex = fRingUsedIndex++ & (fRingSize - 1);
TRACE("Dequeue() usedIndex: %u\n", usedIndex); TRACE("Dequeue() usedIndex: %u\n", usedIndex);
@@ -261,6 +261,9 @@ VirtioQueue::Dequeue(uint32* _usedLength)
*_usedLength = element->len; *_usedLength = element->len;
void* cookie = fDescriptors[descriptorIndex]->Cookie(); void* cookie = fDescriptors[descriptorIndex]->Cookie();
if (_cookie != NULL)
*_cookie = cookie;
uint16 size = fDescriptors[descriptorIndex]->Size(); uint16 size = fDescriptors[descriptorIndex]->Size();
if (size == 0) if (size == 0)
panic("VirtioQueue::Dequeue() size is zero\n"); panic("VirtioQueue::Dequeue() size is zero\n");
@@ -283,7 +286,7 @@ VirtioQueue::Dequeue(uint32* _usedLength)
fRingHeadIndex = descriptorIndex; fRingHeadIndex = descriptorIndex;
TRACE("Dequeue() fRingHeadIndex: %u\n", fRingHeadIndex); TRACE("Dequeue() fRingHeadIndex: %u\n", fRingHeadIndex);
return cookie; return true;
} }
@@ -95,7 +95,7 @@ VirtioRNGDevice::Read(void* _buffer, size_t* _numBytes)
fInterruptCondition.Add(&fInterruptConditionEntry); fInterruptCondition.Add(&fInterruptConditionEntry);
} }
status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &fEntry, status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &fEntry,
this); NULL);
if (result != B_OK) { if (result != B_OK) {
ERROR("queueing failed (%s)\n", strerror(result)); ERROR("queueing failed (%s)\n", strerror(result));
return result; return result;
@@ -131,7 +131,7 @@ VirtioRNGDevice::_RequestCallback(void* driverCookie, void* cookie)
{ {
VirtioRNGDevice* device = (VirtioRNGDevice*)driverCookie; VirtioRNGDevice* device = (VirtioRNGDevice*)driverCookie;
while (device->fVirtio->queue_dequeue(device->fVirtioQueue, NULL) != NULL) while (device->fVirtio->queue_dequeue(device->fVirtioQueue, NULL, NULL))
; ;
device->_RequestInterrupt(); device->_RequestInterrupt();
@@ -275,7 +275,7 @@ VirtioSCSIController::_RequestCallback(void* driverCookie, void* cookie)
VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie; VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie;
while (controller->fVirtio->queue_dequeue( while (controller->fVirtio->queue_dequeue(
controller->fRequestVirtioQueue, NULL) != NULL) { controller->fRequestVirtioQueue, NULL, NULL)) {
} }
controller->_RequestInterrupt(); controller->_RequestInterrupt();
@@ -296,12 +296,9 @@ VirtioSCSIController::_EventCallback(void* driverCookie, void* cookie)
CALLED(); CALLED();
VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie; VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie;
while (true) { virtio_scsi_event* event = NULL;
virtio_scsi_event* event = (virtio_scsi_event*) while (controller->fVirtio->queue_dequeue(controller->fEventVirtioQueue,
controller->fVirtio->queue_dequeue(controller->fEventVirtioQueue, (void**)&event, NULL)) {
NULL);
if (event == NULL)
break;
controller->_EventInterrupt(event); controller->_EventInterrupt(event);
} }
} }
@@ -189,7 +189,7 @@ virtio_block_callback(void* driverCookie, void* cookie)
virtio_block_driver_info* info = (virtio_block_driver_info*)cookie; virtio_block_driver_info* info = (virtio_block_driver_info*)cookie;
// consume all queued elements // consume all queued elements
while (info->virtio->queue_dequeue(info->virtio_queue, NULL) != NULL) while (info->virtio->queue_dequeue(info->virtio_queue, NULL, NULL))
; ;
release_sem_etc(info->sem_cb, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(info->sem_cb, 1, B_DO_NOT_RESCHEDULE);
@@ -171,26 +171,15 @@ get_feature_name(uint32 feature)
static status_t static status_t
virtio_net_drain_queues(virtio_net_driver_info* info) virtio_net_drain_queues(virtio_net_driver_info* info)
{ {
while (true) { BufInfo* buf = NULL;
BufInfo* buf = (BufInfo*)info->virtio->queue_dequeue( while (info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf, NULL))
info->txQueues[0], NULL);
if (buf == NULL)
break;
info->txFreeList.Add(buf); info->txFreeList.Add(buf);
}
while (true) { while (info->virtio->queue_dequeue(info->rxQueues[0], NULL, NULL))
BufInfo* buf = (BufInfo*)info->virtio->queue_dequeue( ;
info->rxQueues[0], NULL);
if (buf == NULL)
break;
}
while (true) { while (info->rxFullList.RemoveHead() != NULL)
BufInfo* buf = info->rxFullList.RemoveHead(); ;
if (buf == NULL)
break;
}
return B_OK; return B_OK;
} }
@@ -565,10 +554,11 @@ virtio_net_read(void* cookie, off_t pos, void* buffer, size_t* _length)
mutex_lock(&info->rxLock); mutex_lock(&info->rxLock);
while (info->rxDone != -1) { while (info->rxDone != -1) {
uint32 usedLength = 0; uint32 usedLength = 0;
BufInfo* buf = (BufInfo*)info->virtio->queue_dequeue( BufInfo* buf = NULL;
info->rxQueues[0], &usedLength); if (!info->virtio->queue_dequeue(info->rxQueues[0], (void**)&buf,
if (buf == NULL) &usedLength) || buf == NULL) {
break; break;
}
buf->rxUsedLength = usedLength; buf->rxUsedLength = usedLength;
info->rxFullList.Add(buf); info->rxFullList.Add(buf);
@@ -622,10 +612,12 @@ virtio_net_write(void* cookie, off_t pos, const void* buffer,
mutex_lock(&info->txLock); mutex_lock(&info->txLock);
while (info->txDone != -1) { while (info->txDone != -1) {
BufInfo* buf = (BufInfo*)info->virtio->queue_dequeue( BufInfo* buf = NULL;
info->txQueues[0], NULL); if (!info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf,
if (buf == NULL) NULL) || buf == NULL) {
break; break;
}
info->txFreeList.Add(buf); info->txFreeList.Add(buf);
} }
} }