From 2ceecd44f94caf5bece78d46c2ef280c6949f34c Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 5 May 2015 18:43:58 +0200 Subject: [PATCH] pci: assign device during pci config cmd write Issue #1216 --- repos/dde_bsd/src/lib/audio/bus.cc | 9 ---- .../dde_ipxe/src/lib/dde_ipxe/dde_support.cc | 10 ---- repos/dde_linux/src/lib/usb/pci_driver.cc | 3 -- repos/dde_linux/src/lib/wifi/pci_driver.cc | 3 -- repos/os/src/drivers/ahci/x86/ahci_device.h | 13 ++--- repos/os/src/drivers/pci/pci_device.cc | 36 +++++++++++++ .../src/drivers/pci/pci_session_component.h | 52 ++++++++----------- repos/os/src/lib/dde_kit/pci_tree.h | 12 ----- 8 files changed, 62 insertions(+), 76 deletions(-) diff --git a/repos/dde_bsd/src/lib/audio/bus.cc b/repos/dde_bsd/src/lib/audio/bus.cc index e11b06f11..af70d6274 100644 --- a/repos/dde_bsd/src/lib/audio/bus.cc +++ b/repos/dde_bsd/src/lib/audio/bus.cc @@ -121,15 +121,6 @@ class Pci_driver : public Bsd::Bus_driver Genode::Ram_dataspace_capability _alloc_dma_memory(Genode::size_t size) { try { - /* trigger that the device gets assigned to this driver (needed by IOMMUs) */ - for (unsigned i = 0; i < 2; i++) - try { - _pci.config_extended(_cap); - break; - } catch (Pci::Device::Quota_exceeded) { - Genode::env()->parent()->upgrade(_pci.cap(), "ram_quota=4096"); - } - char buf[32]; Genode::snprintf(buf, sizeof(buf), "ram_quota=%zu", size); Genode::env()->parent()->upgrade(_pci.cap(), buf); diff --git a/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc b/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc index 82a9e5f79..7dd3f4664 100644 --- a/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc +++ b/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc @@ -200,16 +200,6 @@ struct Pci_driver try { using namespace Genode; - /* trigger that the device gets assigned to this driver */ - for (unsigned i = 0; i < 2; i++) { - try { - _pci.config_extended(_cap); - break; - } catch (Pci::Device::Quota_exceeded) { - Genode::env()->parent()->upgrade(_pci.cap(), "ram_quota=4096"); - } - } - /* transfer quota to pci driver, otherwise it will give us a exception */ char buf[32]; Genode::snprintf(buf, sizeof(buf), "ram_quota=%zd", size); diff --git a/repos/dde_linux/src/lib/usb/pci_driver.cc b/repos/dde_linux/src/lib/usb/pci_driver.cc index 39242894b..8fdda37b3 100644 --- a/repos/dde_linux/src/lib/usb/pci_driver.cc +++ b/repos/dde_linux/src/lib/usb/pci_driver.cc @@ -313,9 +313,6 @@ int pci_register_driver(struct pci_driver *drv) Pci_driver *pci_drv = 0; try { - /* trigger that the device get be assigned to the usb driver */ - pci.config_extended(cap); - /* probe device */ pci_drv = new (env()->heap()) Pci_driver(drv, cap, id); pci.on_destruction(Pci::Connection::KEEP_OPEN); diff --git a/repos/dde_linux/src/lib/wifi/pci_driver.cc b/repos/dde_linux/src/lib/wifi/pci_driver.cc index 08fb585c0..ad8cfc908 100644 --- a/repos/dde_linux/src/lib/wifi/pci_driver.cc +++ b/repos/dde_linux/src/lib/wifi/pci_driver.cc @@ -295,9 +295,6 @@ extern "C" int pci_register_driver(struct pci_driver *drv) try { pci_device_cap = cap; - /* trigger that the device get be assigned to the wifi driver */ - pci()->config_extended(cap); - /* probe device */ pci_drv = new (env()->heap()) Pci_driver(drv, cap, id); pci()->on_destruction(Pci::Connection::KEEP_OPEN); diff --git a/repos/os/src/drivers/ahci/x86/ahci_device.h b/repos/os/src/drivers/ahci/x86/ahci_device.h index 51c4020be..32023de0d 100644 --- a/repos/os/src/drivers/ahci/x86/ahci_device.h +++ b/repos/os/src/drivers/ahci/x86/ahci_device.h @@ -36,6 +36,7 @@ class Ahci_device : public Ahci_device_base CLASS_MASK = 0xffff00U, AHCI_BASE_ID = 0x5, /* resource id of AHCI base addr */ AHCI_INTR_OFF = 0x3c, /* offset of interrupt information in config space */ + PCI_CFG_CMD_REG = 0x4, }; ::Pci::Connection &_pci; @@ -137,6 +138,10 @@ class Ahci_device : public Ahci_device_base " %08x)\n", pci_device->vendor_id(), pci_device->device_id(), pci_device->class_code()); + /* enable Bus Master, Memory Space, I/O Space access by dev */ + pci_device->config_write(PCI_CFG_CMD_REG, 0x7, + ::Pci::Device::ACCESS_16BIT); + /* read and map base address of AHCI controller */ Pci::Device::Resource resource = pci_device->resource(AHCI_BASE_ID); @@ -173,14 +178,6 @@ class Ahci_device : public Ahci_device_base device->_irq->ack_irq(); device->_pci_device = pci_device; - /* trigger assignment of pci device to the ahci driver */ - try { - pci.config_extended(device_cap); - } catch (Pci::Device::Quota_exceeded) { - Genode::env()->parent()->upgrade(pci.cap(), "ram_quota=4096"); - pci.config_extended(device_cap); - } - /* get device ready */ device->_init(pci_device); diff --git a/repos/os/src/drivers/pci/pci_device.cc b/repos/os/src/drivers/pci/pci_device.cc index 5fefcdea3..7d39379be 100644 --- a/repos/os/src/drivers/pci/pci_device.cc +++ b/repos/os/src/drivers/pci/pci_device.cc @@ -60,3 +60,39 @@ Genode::Io_mem_session_capability Pci::Device_component::io_mem(Genode::uint8_t return Genode::Io_mem_session_capability(); } + +void Pci::Device_component::config_write(unsigned char address, unsigned value, + Access_size size) +{ + /* white list of ports which we permit to write */ + switch (address) { + case 0x40 ... 0xff: /* allow access to device-specific registers */ + break; + case PCI_CMD_REG: /* COMMAND register - first byte */ + if (size == Access_size::ACCESS_16BIT) + break; + case PCI_CMD_REG + 1: /* COMMAND register - second byte */ + case 0xd: /* Latency timer */ + if (size == Access_size::ACCESS_8BIT) + break; + case PCI_IRQ_LINE: + /* permitted up to now solely for acpi driver */ + if (address == PCI_IRQ_LINE && _rewrite_irq_line && + size == Access_size::ACCESS_8BIT) + break; + default: + PWRN("%x:%x:%x write access to address=%x value=0x%x " + " size=0x%x got dropped", _device_config.bus_number(), + _device_config.device_number(), + _device_config.function_number(), + address, value, size); + return; + } + + /* assign device to device_pd */ + if (address == PCI_CMD_REG && value & PCI_CMD_DMA && _session) + _session->assign_device(this); + + _device_config.write(&_config_access, address, value, size); +} + diff --git a/repos/os/src/drivers/pci/pci_session_component.h b/repos/os/src/drivers/pci/pci_session_component.h index 9a0562629..aaf66c2be 100644 --- a/repos/os/src/drivers/pci/pci_session_component.h +++ b/repos/os/src/drivers/pci/pci_session_component.h @@ -543,16 +543,32 @@ namespace Pci { _device_list.remove(device); _ep->dissolve(device); - Genode::Io_mem_connection * io_mem = device->get_config_space(); - if (io_mem) - destroy(_md_alloc, io_mem); - if (device->config().valid()) destroy(_device_slab, device); else destroy(_md_alloc, device); } + Genode::Io_mem_dataspace_capability assign_device(Device_component * device) + { + using namespace Genode; + + if (!device || !device->get_config_space().valid()) + return Io_mem_dataspace_capability(); + + Io_mem_dataspace_capability io_mem = device->get_config_space(); + + if (_child) + _child->assign_pci(io_mem); + + /* + * By now forbid usage of extended pci config space dataspace, + * - until required. + */ + // return io_mem; + return Io_mem_dataspace_capability(); + } + Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap) { using namespace Genode; @@ -560,33 +576,7 @@ namespace Pci { Object_pool::Guard device(_ep->lookup_and_lock(device_cap)); - if (!device || device->config_space() == ~0UL) - return Io_mem_dataspace_capability(); - - Io_mem_connection * io_mem = device->get_config_space(); - if (io_mem) - return io_mem->dataspace(); - - try { - io_mem = new (_md_alloc) Io_mem_connection(device->config_space(), - 0x1000); - } catch (Genode::Allocator::Out_of_memory) { - throw Device::Quota_exceeded(); - } catch (Parent::Service_denied) { - return Io_mem_dataspace_capability(); - } - - device->set_config_space(io_mem); - - if (_child) - _child->assign_pci(io_mem->dataspace()); - - /* - * By now forbid usage of extended pci config space dataspace, - * - until required. - */ - // return io_mem->dataspace(); - return Io_mem_dataspace_capability(); + return assign_device(device); } /** diff --git a/repos/os/src/lib/dde_kit/pci_tree.h b/repos/os/src/lib/dde_kit/pci_tree.h index 00ddd2317..64219213c 100644 --- a/repos/os/src/lib/dde_kit/pci_tree.h +++ b/repos/os/src/lib/dde_kit/pci_tree.h @@ -126,18 +126,6 @@ namespace Dde_kit { Ram_dataspace_capability alloc_dma_buffer(Pci::Connection &pci_drv, size_t size) { - /* trigger that the device gets assigned to this driver */ - for (unsigned i = 0; i < 2; i++) { - try { - pci_drv.config_extended(_device); - break; - } catch (Pci::Device::Quota_exceeded) { - if (i == 1) - return Ram_dataspace_capability(); - Genode::env()->parent()->upgrade(pci_drv.cap(), "ram_quota=4096"); - } - } - for (unsigned i = 0; i < 2; i++) { try { return pci_drv.alloc_dma_buffer(size);