hrev45896 adds 2 changesets to branch 'master' old head: 79a2f0c70c6a13c5454b9b7699c14559f5739396 new head: b5ccadd7c26d425ce2d20050e3096d11c664f0e7 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=b5ccadd+%5E79a2f0c ---------------------------------------------------------------------------- 17c5599: Virtio SCSI: add a description for CHANGE feature. b5ccadd: Virtio: implemented indirect descriptors feature. * indirect descriptors count hardcoded to 128. * already activated for virtio_block driver. [ Jérôme Duval <jerome.duval@xxxxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 107 insertions(+), 19 deletions(-) .../kernel/bus_managers/virtio/VirtioDevice.cpp | 3 +- .../kernel/bus_managers/virtio/VirtioPrivate.h | 2 + .../kernel/bus_managers/virtio/VirtioQueue.cpp | 118 ++++++++++++++++--- .../busses/scsi/virtio/VirtioSCSIController.cpp | 3 +- ############################################################################ Commit: 17c55998dc49cc84c859f564fae0e0a442194e49 URL: http://cgit.haiku-os.org/haiku/commit/?id=17c5599 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 23 20:59:01 2013 UTC Virtio SCSI: add a description for CHANGE feature. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp index 0be4903..2a39367 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp @@ -21,6 +21,8 @@ get_feature_name(uint32 feature) return "in out"; case VIRTIO_SCSI_F_HOTPLUG: return "hotplug"; + case VIRTIO_SCSI_F_CHANGE: + return "change"; } return NULL; } @@ -348,4 +350,3 @@ VirtioSCSIController::_RescanChildBus(void *cookie) TRACE("rescan done %p\n", childNode); gDeviceManager->put_node(childNode); } - ############################################################################ Revision: hrev45896 Commit: b5ccadd7c26d425ce2d20050e3096d11c664f0e7 URL: http://cgit.haiku-os.org/haiku/commit/?id=b5ccadd Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 23 21:00:20 2013 UTC Virtio: implemented indirect descriptors feature. * indirect descriptors count hardcoded to 128. * already activated for virtio_block driver. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp index 320d16d..4364748 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp @@ -115,7 +115,7 @@ VirtioDevice::NegociateFeatures(uint32 supported, uint32* negociated, // filter our own features fFeatures &= (VIRTIO_FEATURE_TRANSPORT_MASK - /*| VIRTIO_FEATURE_RING_INDIRECT_DESC*/ | VIRTIO_FEATURE_RING_EVENT_IDX); + | VIRTIO_FEATURE_RING_INDIRECT_DESC | VIRTIO_FEATURE_RING_EVENT_IDX); *negociated = fFeatures; @@ -254,4 +254,3 @@ VirtioDevice::DumpFeatures(const char* title, uint32 features, } TRACE("%s: %s\n", title, features_string); } - diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h index 02844c6..a83eaf8 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h @@ -145,6 +145,8 @@ private: size_t fAreaSize; area_id fArea; + uint16 fIndirectMaxSize; + TransferDescriptor** fDescriptors; }; diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp index 9fa4157..5977785 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp @@ -51,36 +51,69 @@ alloc_mem(void **virt, phys_addr_t *phy, size_t size, uint32 protection, class TransferDescriptor { public: TransferDescriptor(VirtioQueue* queue, - uint16 size, - virtio_callback_func callback, - void *callbackCookie); + uint16 indirectMaxSize); ~TransferDescriptor(); + status_t InitCheck() { return fStatus; } + void Callback(); uint16 Size() { return fDescriptorCount; } + void SetTo(uint16 size, + virtio_callback_func callback, + void *callbackCookie); + void Unset(); + struct vring_desc* Indirect() { return fIndirect; } + phys_addr_t PhysAddr() { return fPhysAddr; } private: + status_t fStatus; VirtioQueue* fQueue; void* fCookie; virtio_callback_func fCallback; + struct vring_desc* fIndirect; size_t fAreaSize; area_id fArea; + phys_addr_t fPhysAddr; uint16 fDescriptorCount; }; -TransferDescriptor::TransferDescriptor(VirtioQueue* queue, uint16 size, - virtio_callback_func callback, void *callbackCookie) +TransferDescriptor::TransferDescriptor(VirtioQueue* queue, uint16 indirectMaxSize) : fQueue(queue), - fCookie(callbackCookie), - fCallback(callback), - fDescriptorCount(size) + fCookie(NULL), + fCallback(NULL), + fIndirect(NULL), + fAreaSize(0), + fArea(-1), + fDescriptorCount(0) { + fStatus = B_OK; + struct vring_desc* virtAddr; + phys_addr_t physAddr; + + if (indirectMaxSize > 0) { + fAreaSize = indirectMaxSize * sizeof(struct vring_desc); + fArea = alloc_mem((void **)&virtAddr, &physAddr, fAreaSize, 0, + "virtqueue"); + if (fArea < B_OK) { + fStatus = fArea; + return; + } + memset(virtAddr, 0, fAreaSize); + fIndirect = virtAddr; + fPhysAddr = physAddr; + + for (uint16 i = 0; i < indirectMaxSize - 1; i++) + fIndirect[i].next = i + 1; + fIndirect[indirectMaxSize - 1].next = UINT16_MAX; + } } TransferDescriptor::~TransferDescriptor() { + if (fArea > B_OK) + delete_area(fArea); } @@ -92,6 +125,25 @@ TransferDescriptor::Callback() } +void +TransferDescriptor::SetTo(uint16 size, virtio_callback_func callback, + void *callbackCookie) +{ + fCookie = callbackCookie; + fCallback = callback; + fDescriptorCount = size; +} + + +void +TransferDescriptor::Unset() +{ + fCookie = NULL; + fCallback = NULL; + fDescriptorCount = 0; +} + + // #pragma mark - @@ -104,7 +156,8 @@ VirtioQueue::VirtioQueue(VirtioDevice* device, uint16 queueNumber, fRingFree(ringSize), fRingHeadIndex(0), fRingUsedIndex(0), - fStatus(B_OK) + fStatus(B_OK), + fIndirectMaxSize(0) { fDescriptors = new(std::nothrow) TransferDescriptor*[fRingSize]; if (fDescriptors == NULL) { @@ -128,6 +181,17 @@ VirtioQueue::VirtioQueue(VirtioDevice* device, uint16 queueNumber, fRing.desc[i].next = i + 1; fRing.desc[fRingSize - 1].next = UINT16_MAX; + if ((fDevice->Features() & VIRTIO_FEATURE_RING_INDIRECT_DESC) != 0) + fIndirectMaxSize = 128; + + for (uint16 i = 0; i < fRingSize; i++) { + fDescriptors[i] = new TransferDescriptor(this, fIndirectMaxSize); + if (fDescriptors[i] == NULL || fDescriptors[i]->InitCheck() != B_OK) { + fStatus = B_NO_MEMORY; + return; + } + } + DisableInterrupt(); device->SetupQueue(fQueueNumber, physAddr); @@ -137,6 +201,9 @@ VirtioQueue::VirtioQueue(VirtioDevice* device, uint16 queueNumber, VirtioQueue::~VirtioQueue() { delete_area(fArea); + for (uint16 i = 0; i < fRingSize; i++) { + delete fDescriptors[i]; + } delete[] fDescriptors; } @@ -191,6 +258,7 @@ VirtioQueue::Finish() fDescriptors[descriptorIndex]->Callback(); uint16 size = fDescriptors[descriptorIndex]->Size(); + fDescriptors[descriptorIndex]->Unset(); fRingFree += size; size--; @@ -203,8 +271,6 @@ VirtioQueue::Finish() if (size > 0) panic("VirtioQueue::Finish() descriptors left %d\n", size); - // TODO TransferDescriptors are leaked, can't delete in interrupt handler. - fRing.desc[index].next = fRingHeadIndex; fRingHeadIndex = descriptorIndex; TRACE("Finish() fRingHeadIndex: %u\n", fRingHeadIndex); @@ -229,10 +295,8 @@ VirtioQueue::QueueRequest(const physical_entry* vector, size_t readVectorCount, return B_BUSY; uint16 insertIndex = fRingHeadIndex; - fDescriptors[insertIndex] = new(std::nothrow) TransferDescriptor(this, - count, callback, callbackCookie); - if (fDescriptors[insertIndex] == NULL) - return B_NO_MEMORY; + fDescriptors[insertIndex]->SetTo(count, callback, + callbackCookie); // enqueue uint16 index = QueueVector(insertIndex, fRing.desc, vector, @@ -254,7 +318,29 @@ VirtioQueue::QueueRequestIndirect(const physical_entry* vector, size_t readVectorCount, size_t writtenVectorCount, virtio_callback_func callback, void *callbackCookie) { - // TODO + CALLED(); + size_t count = readVectorCount + writtenVectorCount; + if (count > fRingFree || count > fIndirectMaxSize) + return B_BUSY; + + uint16 insertIndex = fRingHeadIndex; + fDescriptors[insertIndex]->SetTo(1, callback, + callbackCookie); + + // enqueue + uint16 index = QueueVector(0, fDescriptors[insertIndex]->Indirect(), + vector, readVectorCount, writtenVectorCount); + + fRing.desc[insertIndex].addr = fDescriptors[insertIndex]->PhysAddr(); + fRing.desc[insertIndex].len = index * sizeof(struct vring_desc); + fRing.desc[insertIndex].flags = VRING_DESC_F_INDIRECT; + fRingHeadIndex = fRing.desc[insertIndex].next; + fRingFree--; + + UpdateAvailable(insertIndex); + + NotifyHost(); + return B_OK; }