aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-08-11 01:52:06 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-09-09 16:29:36 -0400
commitdeb2d2ecd43dfc51efe71eed7128fda514da96c6 (patch)
treeba05339620bc285265f88d2c7c43df5fc25b732c /drivers/pci
parent500559a92dd36af7cee95ed2f5b7722fb95a82e7 (diff)
PCI/GPU: implement VGA arbitration on Linux
Background: Graphic devices are accessed through ranges in I/O or memory space. While most modern devices allow relocation of such ranges, some "Legacy" VGA devices implemented on PCI will typically have the same "hard-decoded" addresses as they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994 Standard for Boot (Initialization Configuration) Firmware Revision 2.1" Section 7, Legacy Devices. The Resource Access Control (RAC) module inside the X server currently does the task of arbitration when more than one legacy device co-exists on the same machine. But the problem happens when these devices are trying to be accessed by different userspace clients (e.g. two server in parallel). Their address assignments conflict. Therefore an arbitration scheme _outside_ of the X server is needed to control the sharing of these resources. This document introduces the operation of the VGA arbiter implemented for Linux kernel. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7d55039ffa05..bd993351db45 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2520,6 +2520,50 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
2520 return 0; 2520 return 0;
2521} 2521}
2522 2522
2523/**
2524 * pci_set_vga_state - set VGA decode state on device and parents if requested
2525 * @dev the PCI device
2526 * @decode - true = enable decoding, false = disable decoding
2527 * @command_bits PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
2528 * @change_bridge - traverse ancestors and change bridges
2529 */
2530int pci_set_vga_state(struct pci_dev *dev, bool decode,
2531 unsigned int command_bits, bool change_bridge)
2532{
2533 struct pci_bus *bus;
2534 struct pci_dev *bridge;
2535 u16 cmd;
2536
2537 WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
2538
2539 pci_read_config_word(dev, PCI_COMMAND, &cmd);
2540 if (decode == true)
2541 cmd |= command_bits;
2542 else
2543 cmd &= ~command_bits;
2544 pci_write_config_word(dev, PCI_COMMAND, cmd);
2545
2546 if (change_bridge == false)
2547 return 0;
2548
2549 bus = dev->bus;
2550 while (bus) {
2551 bridge = bus->self;
2552 if (bridge) {
2553 pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
2554 &cmd);
2555 if (decode == true)
2556 cmd |= PCI_BRIDGE_CTL_VGA;
2557 else
2558 cmd &= ~PCI_BRIDGE_CTL_VGA;
2559 pci_write_config_word(bridge, PCI_BRIDGE_CONTROL,
2560 cmd);
2561 }
2562 bus = bus->parent;
2563 }
2564 return 0;
2565}
2566
2523#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE 2567#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
2524static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; 2568static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
2525spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; 2569spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED;