aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2009-12-13 08:11:34 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 16:15:19 -0800
commit45b4cdd57ef0e57555b2ab61b584784819b39365 (patch)
tree1e08008e0cdc57252022b5ad1a0e3029c7e96f99 /drivers/pci/probe.c
parent9be60ca0497a2563662fde4c9007841c3b79a742 (diff)
PCI: Add support for AGP in cur/max bus speed
Take advantage of some gaps in the table to fit in support for AGP speeds. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 188ee9cf060..2803ab96a98 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -437,11 +437,56 @@ void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
}
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
+static unsigned char agp_speeds[] = {
+ AGP_UNKNOWN,
+ AGP_1X,
+ AGP_2X,
+ AGP_4X,
+ AGP_8X
+};
+
+static enum pci_bus_speed agp_speed(int agp3, int agpstat)
+{
+ int index = 0;
+
+ if (agpstat & 4)
+ index = 3;
+ else if (agpstat & 2)
+ index = 2;
+ else if (agpstat & 1)
+ index = 1;
+ else
+ goto out;
+
+ if (agp3) {
+ index += 2;
+ if (index == 5)
+ index = 0;
+ }
+
+ out:
+ return agp_speeds[index];
+}
+
+
static void pci_set_bus_speed(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
int pos;
+ pos = pci_find_capability(bridge, PCI_CAP_ID_AGP);
+ if (!pos)
+ pos = pci_find_capability(bridge, PCI_CAP_ID_AGP3);
+ if (pos) {
+ u32 agpstat, agpcmd;
+
+ pci_read_config_dword(bridge, pos + PCI_AGP_STATUS, &agpstat);
+ bus->max_bus_speed = agp_speed(agpstat & 8, agpstat & 7);
+
+ pci_read_config_dword(bridge, pos + PCI_AGP_COMMAND, &agpcmd);
+ bus->cur_bus_speed = agp_speed(agpstat & 8, agpcmd & 7);
+ }
+
pos = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
if (pos) {
u16 status;