]>
Commit | Line | Data |
---|---|---|
45426b3c GKH |
1 | From 6fd024893911dcb51b4a0aa71971db5ba38f7071 Mon Sep 17 00:00:00 2001 |
2 | From: Ben Hutchings <ben@decadent.org.uk> | |
3 | Date: Wed, 24 Mar 2010 03:36:31 +0000 | |
4 | Subject: amd64-agp: Probe unknown AGP devices the right way | |
5 | ||
6 | From: Ben Hutchings <ben@decadent.org.uk> | |
7 | ||
8 | commit 6fd024893911dcb51b4a0aa71971db5ba38f7071 upstream. | |
9 | ||
10 | The current initialisation code probes 'unsupported' AGP devices | |
11 | simply by calling its own probe function. It does not lock these | |
12 | devices or even check whether another driver is already bound to | |
13 | them. | |
14 | ||
15 | We must use the device core to manage this. So if the specific | |
16 | device id table didn't match anything and agp_try_unsupported=1, | |
17 | switch the device id table and call driver_attach() again. | |
18 | ||
19 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | |
20 | Signed-off-by: Dave Airlie <airlied@redhat.com> | |
21 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
22 | ||
23 | --- | |
24 | drivers/char/agp/amd64-agp.c | 27 +++++++++++++++------------ | |
25 | 1 file changed, 15 insertions(+), 12 deletions(-) | |
26 | ||
27 | --- a/drivers/char/agp/amd64-agp.c | |
28 | +++ b/drivers/char/agp/amd64-agp.c | |
29 | @@ -499,6 +499,10 @@ static int __devinit agp_amd64_probe(str | |
30 | u8 cap_ptr; | |
31 | int err; | |
32 | ||
33 | + /* The Highlander principle */ | |
34 | + if (agp_bridges_found) | |
35 | + return -ENODEV; | |
36 | + | |
37 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | |
38 | if (!cap_ptr) | |
39 | return -ENODEV; | |
40 | @@ -562,6 +566,8 @@ static void __devexit agp_amd64_remove(s | |
41 | amd64_aperture_sizes[bridge->aperture_size_idx].size); | |
42 | agp_remove_bridge(bridge); | |
43 | agp_put_bridge(bridge); | |
44 | + | |
45 | + agp_bridges_found--; | |
46 | } | |
47 | ||
48 | #ifdef CONFIG_PM | |
49 | @@ -709,6 +715,11 @@ static struct pci_device_id agp_amd64_pc | |
50 | ||
51 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); | |
52 | ||
53 | +static DEFINE_PCI_DEVICE_TABLE(agp_amd64_pci_promisc_table) = { | |
54 | + { PCI_DEVICE_CLASS(0, 0) }, | |
55 | + { } | |
56 | +}; | |
57 | + | |
58 | static struct pci_driver agp_amd64_pci_driver = { | |
59 | .name = "agpgart-amd64", | |
60 | .id_table = agp_amd64_pci_table, | |
61 | @@ -733,7 +744,6 @@ int __init agp_amd64_init(void) | |
62 | return err; | |
63 | ||
64 | if (agp_bridges_found == 0) { | |
65 | - struct pci_dev *dev; | |
66 | if (!agp_try_unsupported && !agp_try_unsupported_boot) { | |
67 | printk(KERN_INFO PFX "No supported AGP bridge found.\n"); | |
68 | #ifdef MODULE | |
69 | @@ -749,17 +759,10 @@ int __init agp_amd64_init(void) | |
70 | return -ENODEV; | |
71 | ||
72 | /* Look for any AGP bridge */ | |
73 | - dev = NULL; | |
74 | - err = -ENODEV; | |
75 | - for_each_pci_dev(dev) { | |
76 | - if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) | |
77 | - continue; | |
78 | - /* Only one bridge supported right now */ | |
79 | - if (agp_amd64_probe(dev, NULL) == 0) { | |
80 | - err = 0; | |
81 | - break; | |
82 | - } | |
83 | - } | |
84 | + agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table; | |
85 | + err = driver_attach(&agp_amd64_pci_driver.driver); | |
86 | + if (err == 0 && agp_bridges_found == 0) | |
87 | + err = -ENODEV; | |
88 | } | |
89 | return err; | |
90 | } |