[haiku-commits] haiku: hrev51902 - src/add-ons/kernel/bus_managers/virtio src/add-ons/kernel/busses/virtio headers/private/virtio

  • From: jerome.duval@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 26 Apr 2018 02:34:22 -0400 (EDT)

hrev51902 adds 1 changeset to branch 'master'
old head: 6e82e428596071bbde44e296d04740f1f5d54d03
new head: 61cd7e85d7ec458ad244d2074ddc5a437b81b742
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=61cd7e85d7ec+%5E6e82e4285960

----------------------------------------------------------------------------

61cd7e85d7ec: virtio: add API to uninit a device.
  
  * free interrupts, free queues, return to init state.
  * this will be used by virtio_net on interface uninit.
  
  Change-Id: I7c1e6facc37cf6bfe19628576fdf2c0bac9e5c38

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev51902
Commit:      61cd7e85d7ec458ad244d2074ddc5a437b81b742
URL:         https://git.haiku-os.org/haiku/commit/?id=61cd7e85d7ec
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Sat Apr 21 14:52:10 2018 UTC

----------------------------------------------------------------------------

6 files changed, 112 insertions(+), 20 deletions(-)
headers/private/virtio/virtio.h                  |  5 ++
.../kernel/bus_managers/virtio/VirtioDevice.cpp  | 64 +++++++++++++++-----
.../kernel/bus_managers/virtio/VirtioModule.cpp  | 22 ++++++-
.../kernel/bus_managers/virtio/VirtioPrivate.h   |  6 +-
.../kernel/bus_managers/virtio/VirtioQueue.cpp   |  2 +-
src/add-ons/kernel/busses/virtio/virtio_pci.cpp  | 33 +++++++++-

----------------------------------------------------------------------------

diff --git a/headers/private/virtio/virtio.h b/headers/private/virtio/virtio.h
index 1afd5dd052..24b44e15c1 100644
--- a/headers/private/virtio/virtio.h
+++ b/headers/private/virtio/virtio.h
@@ -85,6 +85,7 @@ typedef struct {
        uint16  (*get_queue_ring_size)(void* cookie, uint16 queue);
        status_t (*setup_queue)(void* cookie, uint16 queue, phys_addr_t phy);
        status_t (*setup_interrupt)(void* cookie, uint16 queueCount);
+       status_t (*free_interrupt)(void* cookie);
        void    (*notify_queue)(void* cookie, uint16 queue);
 } virtio_sim_interface;
 
@@ -104,9 +105,13 @@ typedef struct {
        status_t (*alloc_queues)(virtio_device cookie, size_t count,
                virtio_queue* queues);
 
+       void (*free_queues)(virtio_device cookie);
+
        status_t (*setup_interrupt)(virtio_device cookie,
                virtio_intr_func config_handler, void* driverCookie);
 
+       status_t (*free_interrupts)(virtio_device cookie);
+
        status_t (*queue_setup_interrupt)(virtio_queue queue,
                virtio_callback_func handler, void* cookie);
 
diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp 
b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp
index 0fa3985fde..ab5e8671e7 100644
--- a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp
+++ b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2013, 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -63,6 +63,7 @@ VirtioDevice::VirtioDevice(device_node *node)
        fConfigHandler(NULL),
        fDriverCookie(NULL)
 {
+       CALLED();
        device_node *parent = gDeviceManager->get_parent_node(node);
        fStatus = gDeviceManager->get_driver(parent,
                (driver_module_info **)&fController, &fCookie);
@@ -86,10 +87,10 @@ VirtioDevice::VirtioDevice(device_node *node)
 
 VirtioDevice::~VirtioDevice()
 {
-       for (size_t index = 0; index < fQueueCount; index++) {
-               delete fQueues[index];
+       if (fQueues != NULL) {
+               _DestroyQueues(fQueueCount);
        }
-       delete fQueues;
+       fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_RESET);
 }
 
 
@@ -109,7 +110,7 @@ VirtioDevice::NegotiateFeatures(uint32 supported, uint32* 
negotiated,
        if (status != B_OK)
                return status;
 
-       DumpFeatures("read features", fFeatures, get_feature_name);
+       _DumpFeatures("read features", fFeatures, get_feature_name);
 
        fFeatures &= supported;
 
@@ -119,7 +120,7 @@ VirtioDevice::NegotiateFeatures(uint32 supported, uint32* 
negotiated,
 
        *negotiated = fFeatures;
 
-       DumpFeatures("negotiated features", fFeatures, get_feature_name);
+       _DumpFeatures("negotiated features", fFeatures, get_feature_name);
 
        return fController->write_guest_features(fCookie, fFeatures);
 }
@@ -148,13 +149,11 @@ VirtioDevice::AllocateQueues(size_t count, virtio_queue 
*queues)
        if (count > VIRTIO_VIRTQUEUES_MAX_COUNT || queues == NULL)
                return B_BAD_VALUE;
 
-       status_t status = B_OK;
        fQueues = new(std::nothrow) VirtioQueue*[count];
-       if (fQueues == NULL) {
-               status = B_NO_MEMORY;
-               goto err;
-       }
+       if (fQueues == NULL)
+               return B_NO_MEMORY;
 
+       status_t status = B_OK;
        fQueueCount = count;
        for (size_t index = 0; index < count; index++) {
                uint16 size = fController->get_queue_ring_size(fCookie, index);
@@ -163,14 +162,24 @@ VirtioDevice::AllocateQueues(size_t count, virtio_queue 
*queues)
                status = B_NO_MEMORY;
                if (fQueues[index] != NULL)
                        status = fQueues[index]->InitCheck();
-               if (status != B_OK)
-                       goto err;
+               if (status != B_OK) {
+                       _DestroyQueues(index + 1);
+                       return status;
+               }
        }
 
        return B_OK;
+}
 
-err:
-       return status;
+
+void
+VirtioDevice::FreeQueues()
+{
+       if (fQueues != NULL)
+               _DestroyQueues(fQueueCount);
+
+       fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_RESET);
+       fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_DRIVER);
 }
 
 
@@ -192,6 +201,18 @@ VirtioDevice::SetupInterrupt(virtio_intr_func 
configHandler, void *driverCookie)
 }
 
 
+status_t
+VirtioDevice::FreeInterrupts()
+{
+       for (size_t index = 0; index < fQueueCount; index++)
+               fQueues[index]->DisableInterrupt();
+
+       fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_DRIVER);
+
+       return fController->free_interrupt(fCookie);
+}
+
+
 status_t
 VirtioDevice::SetupQueue(uint16 queueNumber, phys_addr_t physAddr)
 {
@@ -236,7 +257,18 @@ VirtioDevice::ConfigInterrupt()
 
 
 void
-VirtioDevice::DumpFeatures(const char* title, uint32 features,
+VirtioDevice::_DestroyQueues(size_t count)
+{
+       for (size_t i = 0; i < count; i++) {
+               delete fQueues[i];
+       }
+       delete[] fQueues;
+       fQueues = NULL;
+}
+
+
+void
+VirtioDevice::_DumpFeatures(const char* title, uint32 features,
        const char* (*get_feature_name)(uint32))
 {
        char features_string[512] = "";
diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp 
b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp
index 7515f0b44d..74b77a5dac 100644
--- a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp
+++ b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2013, 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -94,6 +94,15 @@ virtio_alloc_queues(virtio_device _device, size_t count, 
virtio_queue *queues)
 }
 
 
+void
+virtio_free_queues(virtio_device _device)
+{
+       CALLED();
+       VirtioDevice *device = (VirtioDevice *)_device;
+       device->FreeQueues();
+}
+
+
 status_t
 virtio_setup_interrupt(virtio_device _device, virtio_intr_func config_handler,
        void *driverCookie)
@@ -104,6 +113,15 @@ virtio_setup_interrupt(virtio_device _device, 
virtio_intr_func config_handler,
 }
 
 
+status_t
+virtio_free_interrupts(virtio_device _device)
+{
+       CALLED();
+       VirtioDevice *device = (VirtioDevice *)_device;
+       return device->FreeInterrupts();
+}
+
+
 status_t
 virtio_queue_setup_interrupt(virtio_queue _queue, virtio_callback_func handler,
        void *cookie)
@@ -260,7 +278,9 @@ virtio_device_interface virtio_device_module = {
        virtio_read_device_config,
        virtio_write_device_config,
        virtio_alloc_queues,
+       virtio_free_queues,
        virtio_setup_interrupt,
+       virtio_free_interrupts,
        virtio_queue_setup_interrupt,
        virtio_queue_request,
        virtio_queue_request_v,
diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h 
b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h
index b6db8a2744..f658eda0d7 100644
--- a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h
+++ b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h
@@ -56,8 +56,10 @@ public:
 
                        status_t                        AllocateQueues(size_t 
count,
                                                                        
virtio_queue *queues);
+                       void                            FreeQueues();
                        status_t                        
SetupInterrupt(virtio_intr_func config_handler,
                                                                        void 
*driverCookie);
+                       status_t                        FreeInterrupts();
 
                        uint16                          Alignment() const { 
return fAlignment; }
                        uint32                          Features() const { 
return fFeatures; }
@@ -72,9 +74,11 @@ public:
                        status_t                        ConfigInterrupt();
 
 private:
-                       void                            DumpFeatures(const 
char* title,
+                       void                            _DumpFeatures(const 
char* title,
                                                                        uint32 
features,
                                                                        const 
char* (*get_feature_name)(uint32));
+                       void                            _DestroyQueues(size_t 
count);
+
 
 
                        device_node *           fNode;
diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp 
b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
index 4ed23b33b0..6d067c62a3 100644
--- a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
+++ b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2013, 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
diff --git a/src/add-ons/kernel/busses/virtio/virtio_pci.cpp 
b/src/add-ons/kernel/busses/virtio/virtio_pci.cpp
index c7f695dc9f..c969d132e7 100644
--- a/src/add-ons/kernel/busses/virtio/virtio_pci.cpp
+++ b/src/add-ons/kernel/busses/virtio/virtio_pci.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2013, 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -390,6 +390,36 @@ setup_interrupt(void* cookie, uint16 queueCount)
 }
 
 
+status_t
+free_interrupt(void* cookie)
+{
+       CALLED();
+       virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
+       pci_info *pciInfo = &bus->info;
+
+       if (bus->irq_type == VIRTIO_IRQ_MSI_X) {
+               remove_io_interrupt_handler(bus->irq, 
virtio_pci_config_interrupt,
+                       bus);
+               int32 irq = bus->irq + 1;
+               for (int32 queue = 0; queue < bus->queue_count; queue++, irq++) 
{
+                       remove_io_interrupt_handler(irq, 
virtio_pci_queue_interrupt,
+                               &bus->cookies[queue]);
+               }
+               delete[] bus->cookies;
+
+       } else
+               remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, 
bus);
+
+       if (sPCIx86Module != NULL && bus->irq_type != VIRTIO_IRQ_LEGACY) {
+               sPCIx86Module->disable_msi(pciInfo->bus, pciInfo->device,
+                       pciInfo->function);
+               sPCIx86Module->unconfigure_msi(pciInfo->bus, pciInfo->device,
+                       pciInfo->function);
+       }
+       return B_OK;
+}
+
+
 void
 notify_queue(void* cookie, uint16 queue)
 {
@@ -640,6 +670,7 @@ static virtio_sim_interface gVirtioPCIDeviceModule = {
        get_queue_ring_size,
        setup_queue,
        setup_interrupt,
+       free_interrupt,
        notify_queue
 };
 


Other related posts:

  • » [haiku-commits] haiku: hrev51902 - src/add-ons/kernel/bus_managers/virtio src/add-ons/kernel/busses/virtio headers/private/virtio - jerome . duval