aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/vga
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/gpu/vga
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/gpu/vga')
-rw-r--r--drivers/gpu/vga/Kconfig3
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c348
-rw-r--r--drivers/gpu/vga/vgaarb.c98
3 files changed, 185 insertions, 264 deletions
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index 29437eabe09..96c83a9a76b 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -1,7 +1,7 @@
1config VGA_ARB 1config VGA_ARB
2 bool "VGA Arbitration" if EXPERT 2 bool "VGA Arbitration" if EXPERT
3 default y 3 default y
4 depends on (PCI && !S390) 4 depends on PCI
5 help 5 help
6 Some "legacy" VGA devices implemented on PCI typically have the same 6 Some "legacy" VGA devices implemented on PCI typically have the same
7 hard-decoded addresses as they did on ISA. When multiple PCI devices 7 hard-decoded addresses as they did on ISA. When multiple PCI devices
@@ -21,7 +21,6 @@ config VGA_SWITCHEROO
21 bool "Laptop Hybrid Graphics - GPU switching support" 21 bool "Laptop Hybrid Graphics - GPU switching support"
22 depends on X86 22 depends on X86
23 depends on ACPI 23 depends on ACPI
24 select VGA_ARB
25 help 24 help
26 Many laptops released in 2008/9/10 have two GPUs with a multiplexer 25 Many laptops released in 2008/9/10 have two GPUs with a multiplexer
27 to switch between them. This adds support for dynamic switching when 26 to switch between them. This adds support for dynamic switching when
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index fa60add0ff6..58434e804d9 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -18,6 +18,7 @@
18 */ 18 */
19 19
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/dmi.h>
21#include <linux/seq_file.h> 22#include <linux/seq_file.h>
22#include <linux/uaccess.h> 23#include <linux/uaccess.h>
23#include <linux/fs.h> 24#include <linux/fs.h>
@@ -27,16 +28,15 @@
27#include <linux/pci.h> 28#include <linux/pci.h>
28#include <linux/vga_switcheroo.h> 29#include <linux/vga_switcheroo.h>
29 30
30#include <linux/vgaarb.h>
31
32struct vga_switcheroo_client { 31struct vga_switcheroo_client {
33 struct pci_dev *pdev; 32 struct pci_dev *pdev;
34 struct fb_info *fb_info; 33 struct fb_info *fb_info;
35 int pwr_state; 34 int pwr_state;
36 const struct vga_switcheroo_client_ops *ops; 35 void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
36 void (*reprobe)(struct pci_dev *pdev);
37 bool (*can_switch)(struct pci_dev *pdev);
37 int id; 38 int id;
38 bool active; 39 bool active;
39 struct list_head list;
40}; 40};
41 41
42static DEFINE_MUTEX(vgasr_mutex); 42static DEFINE_MUTEX(vgasr_mutex);
@@ -51,52 +51,16 @@ struct vgasr_priv {
51 struct dentry *switch_file; 51 struct dentry *switch_file;
52 52
53 int registered_clients; 53 int registered_clients;
54 struct list_head clients; 54 struct vga_switcheroo_client clients[VGA_SWITCHEROO_MAX_CLIENTS];
55 55
56 struct vga_switcheroo_handler *handler; 56 struct vga_switcheroo_handler *handler;
57}; 57};
58 58
59#define ID_BIT_AUDIO 0x100
60#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO)
61#define client_is_vga(c) ((c)->id == -1 || !client_is_audio(c))
62#define client_id(c) ((c)->id & ~ID_BIT_AUDIO)
63
64static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv); 59static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
65static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv); 60static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
66 61
67/* only one switcheroo per system */ 62/* only one switcheroo per system */
68static struct vgasr_priv vgasr_priv = { 63static struct vgasr_priv vgasr_priv;
69 .clients = LIST_HEAD_INIT(vgasr_priv.clients),
70};
71
72static bool vga_switcheroo_ready(void)
73{
74 /* we're ready if we get two clients + handler */
75 return !vgasr_priv.active &&
76 vgasr_priv.registered_clients == 2 && vgasr_priv.handler;
77}
78
79static void vga_switcheroo_enable(void)
80{
81 int ret;
82 struct vga_switcheroo_client *client;
83
84 /* call the handler to init */
85 if (vgasr_priv.handler->init)
86 vgasr_priv.handler->init();
87
88 list_for_each_entry(client, &vgasr_priv.clients, list) {
89 if (client->id != -1)
90 continue;
91 ret = vgasr_priv.handler->get_client_id(client->pdev);
92 if (ret < 0)
93 return;
94
95 client->id = ret;
96 }
97 vga_switcheroo_debugfs_init(&vgasr_priv);
98 vgasr_priv.active = true;
99}
100 64
101int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) 65int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
102{ 66{
@@ -107,10 +71,6 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
107 } 71 }
108 72
109 vgasr_priv.handler = handler; 73 vgasr_priv.handler = handler;
110 if (vga_switcheroo_ready()) {
111 printk(KERN_INFO "vga_switcheroo: enabled\n");
112 vga_switcheroo_enable();
113 }
114 mutex_unlock(&vgasr_mutex); 74 mutex_unlock(&vgasr_mutex);
115 return 0; 75 return 0;
116} 76}
@@ -120,120 +80,78 @@ void vga_switcheroo_unregister_handler(void)
120{ 80{
121 mutex_lock(&vgasr_mutex); 81 mutex_lock(&vgasr_mutex);
122 vgasr_priv.handler = NULL; 82 vgasr_priv.handler = NULL;
123 if (vgasr_priv.active) {
124 pr_info("vga_switcheroo: disabled\n");
125 vga_switcheroo_debugfs_fini(&vgasr_priv);
126 vgasr_priv.active = false;
127 }
128 mutex_unlock(&vgasr_mutex); 83 mutex_unlock(&vgasr_mutex);
129} 84}
130EXPORT_SYMBOL(vga_switcheroo_unregister_handler); 85EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
131 86
132static int register_client(struct pci_dev *pdev, 87static void vga_switcheroo_enable(void)
133 const struct vga_switcheroo_client_ops *ops,
134 int id, bool active)
135{ 88{
136 struct vga_switcheroo_client *client; 89 int i;
90 int ret;
91 /* call the handler to init */
92 vgasr_priv.handler->init();
137 93
138 client = kzalloc(sizeof(*client), GFP_KERNEL); 94 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
139 if (!client) 95 ret = vgasr_priv.handler->get_client_id(vgasr_priv.clients[i].pdev);
140 return -ENOMEM; 96 if (ret < 0)
97 return;
141 98
142 client->pwr_state = VGA_SWITCHEROO_ON; 99 vgasr_priv.clients[i].id = ret;
143 client->pdev = pdev; 100 }
144 client->ops = ops; 101 vga_switcheroo_debugfs_init(&vgasr_priv);
145 client->id = id; 102 vgasr_priv.active = true;
146 client->active = active; 103}
147 104
148 mutex_lock(&vgasr_mutex); 105int vga_switcheroo_register_client(struct pci_dev *pdev,
149 list_add_tail(&client->list, &vgasr_priv.clients); 106 void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
150 if (client_is_vga(client)) 107 void (*reprobe)(struct pci_dev *pdev),
151 vgasr_priv.registered_clients++; 108 bool (*can_switch)(struct pci_dev *pdev))
109{
110 int index;
152 111
153 if (vga_switcheroo_ready()) { 112 mutex_lock(&vgasr_mutex);
113 /* don't do IGD vs DIS here */
114 if (vgasr_priv.registered_clients & 1)
115 index = 1;
116 else
117 index = 0;
118
119 vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
120 vgasr_priv.clients[index].pdev = pdev;
121 vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
122 vgasr_priv.clients[index].reprobe = reprobe;
123 vgasr_priv.clients[index].can_switch = can_switch;
124 vgasr_priv.clients[index].id = -1;
125 if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
126 vgasr_priv.clients[index].active = true;
127
128 vgasr_priv.registered_clients |= (1 << index);
129
130 /* if we get two clients + handler */
131 if (vgasr_priv.registered_clients == 0x3 && vgasr_priv.handler) {
154 printk(KERN_INFO "vga_switcheroo: enabled\n"); 132 printk(KERN_INFO "vga_switcheroo: enabled\n");
155 vga_switcheroo_enable(); 133 vga_switcheroo_enable();
156 } 134 }
157 mutex_unlock(&vgasr_mutex); 135 mutex_unlock(&vgasr_mutex);
158 return 0; 136 return 0;
159} 137}
160
161int vga_switcheroo_register_client(struct pci_dev *pdev,
162 const struct vga_switcheroo_client_ops *ops)
163{
164 return register_client(pdev, ops, -1,
165 pdev == vga_default_device());
166}
167EXPORT_SYMBOL(vga_switcheroo_register_client); 138EXPORT_SYMBOL(vga_switcheroo_register_client);
168 139
169int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
170 const struct vga_switcheroo_client_ops *ops,
171 int id, bool active)
172{
173 return register_client(pdev, ops, id | ID_BIT_AUDIO, active);
174}
175EXPORT_SYMBOL(vga_switcheroo_register_audio_client);
176
177static struct vga_switcheroo_client *
178find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
179{
180 struct vga_switcheroo_client *client;
181 list_for_each_entry(client, head, list)
182 if (client->pdev == pdev)
183 return client;
184 return NULL;
185}
186
187static struct vga_switcheroo_client *
188find_client_from_id(struct list_head *head, int client_id)
189{
190 struct vga_switcheroo_client *client;
191 list_for_each_entry(client, head, list)
192 if (client->id == client_id)
193 return client;
194 return NULL;
195}
196
197static struct vga_switcheroo_client *
198find_active_client(struct list_head *head)
199{
200 struct vga_switcheroo_client *client;
201 list_for_each_entry(client, head, list)
202 if (client->active && client_is_vga(client))
203 return client;
204 return NULL;
205}
206
207int vga_switcheroo_get_client_state(struct pci_dev *pdev)
208{
209 struct vga_switcheroo_client *client;
210
211 client = find_client_from_pci(&vgasr_priv.clients, pdev);
212 if (!client)
213 return VGA_SWITCHEROO_NOT_FOUND;
214 if (!vgasr_priv.active)
215 return VGA_SWITCHEROO_INIT;
216 return client->pwr_state;
217}
218EXPORT_SYMBOL(vga_switcheroo_get_client_state);
219
220void vga_switcheroo_unregister_client(struct pci_dev *pdev) 140void vga_switcheroo_unregister_client(struct pci_dev *pdev)
221{ 141{
222 struct vga_switcheroo_client *client; 142 int i;
223 143
224 mutex_lock(&vgasr_mutex); 144 mutex_lock(&vgasr_mutex);
225 client = find_client_from_pci(&vgasr_priv.clients, pdev); 145 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
226 if (client) { 146 if (vgasr_priv.clients[i].pdev == pdev) {
227 if (client_is_vga(client)) 147 vgasr_priv.registered_clients &= ~(1 << i);
228 vgasr_priv.registered_clients--; 148 break;
229 list_del(&client->list); 149 }
230 kfree(client);
231 }
232 if (vgasr_priv.active && vgasr_priv.registered_clients < 2) {
233 printk(KERN_INFO "vga_switcheroo: disabled\n");
234 vga_switcheroo_debugfs_fini(&vgasr_priv);
235 vgasr_priv.active = false;
236 } 150 }
151
152 printk(KERN_INFO "vga_switcheroo: disabled\n");
153 vga_switcheroo_debugfs_fini(&vgasr_priv);
154 vgasr_priv.active = false;
237 mutex_unlock(&vgasr_mutex); 155 mutex_unlock(&vgasr_mutex);
238} 156}
239EXPORT_SYMBOL(vga_switcheroo_unregister_client); 157EXPORT_SYMBOL(vga_switcheroo_unregister_client);
@@ -241,29 +159,29 @@ EXPORT_SYMBOL(vga_switcheroo_unregister_client);
241void vga_switcheroo_client_fb_set(struct pci_dev *pdev, 159void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
242 struct fb_info *info) 160 struct fb_info *info)
243{ 161{
244 struct vga_switcheroo_client *client; 162 int i;
245 163
246 mutex_lock(&vgasr_mutex); 164 mutex_lock(&vgasr_mutex);
247 client = find_client_from_pci(&vgasr_priv.clients, pdev); 165 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
248 if (client) 166 if (vgasr_priv.clients[i].pdev == pdev) {
249 client->fb_info = info; 167 vgasr_priv.clients[i].fb_info = info;
168 break;
169 }
170 }
250 mutex_unlock(&vgasr_mutex); 171 mutex_unlock(&vgasr_mutex);
251} 172}
252EXPORT_SYMBOL(vga_switcheroo_client_fb_set); 173EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
253 174
254static int vga_switcheroo_show(struct seq_file *m, void *v) 175static int vga_switcheroo_show(struct seq_file *m, void *v)
255{ 176{
256 struct vga_switcheroo_client *client; 177 int i;
257 int i = 0;
258 mutex_lock(&vgasr_mutex); 178 mutex_lock(&vgasr_mutex);
259 list_for_each_entry(client, &vgasr_priv.clients, list) { 179 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
260 seq_printf(m, "%d:%s%s:%c:%s:%s\n", i, 180 seq_printf(m, "%d:%s:%c:%s:%s\n", i,
261 client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD", 181 vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
262 client_is_vga(client) ? "" : "-Audio", 182 vgasr_priv.clients[i].active ? '+' : ' ',
263 client->active ? '+' : ' ', 183 vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
264 client->pwr_state ? "Pwr" : "Off", 184 pci_name(vgasr_priv.clients[i].pdev));
265 pci_name(client->pdev));
266 i++;
267 } 185 }
268 mutex_unlock(&vgasr_mutex); 186 mutex_unlock(&vgasr_mutex);
269 return 0; 187 return 0;
@@ -279,7 +197,7 @@ static int vga_switchon(struct vga_switcheroo_client *client)
279 if (vgasr_priv.handler->power_state) 197 if (vgasr_priv.handler->power_state)
280 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON); 198 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
281 /* call the driver callback to turn on device */ 199 /* call the driver callback to turn on device */
282 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON); 200 client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
283 client->pwr_state = VGA_SWITCHEROO_ON; 201 client->pwr_state = VGA_SWITCHEROO_ON;
284 return 0; 202 return 0;
285} 203}
@@ -287,37 +205,34 @@ static int vga_switchon(struct vga_switcheroo_client *client)
287static int vga_switchoff(struct vga_switcheroo_client *client) 205static int vga_switchoff(struct vga_switcheroo_client *client)
288{ 206{
289 /* call the driver callback to turn off device */ 207 /* call the driver callback to turn off device */
290 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF); 208 client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
291 if (vgasr_priv.handler->power_state) 209 if (vgasr_priv.handler->power_state)
292 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF); 210 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
293 client->pwr_state = VGA_SWITCHEROO_OFF; 211 client->pwr_state = VGA_SWITCHEROO_OFF;
294 return 0; 212 return 0;
295} 213}
296 214
297static void set_audio_state(int id, int state)
298{
299 struct vga_switcheroo_client *client;
300
301 client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO);
302 if (client && client->pwr_state != state) {
303 client->ops->set_gpu_state(client->pdev, state);
304 client->pwr_state = state;
305 }
306}
307
308/* stage one happens before delay */ 215/* stage one happens before delay */
309static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) 216static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
310{ 217{
311 struct vga_switcheroo_client *active; 218 int i;
219 struct vga_switcheroo_client *active = NULL;
312 220
313 active = find_active_client(&vgasr_priv.clients); 221 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
222 if (vgasr_priv.clients[i].active == true) {
223 active = &vgasr_priv.clients[i];
224 break;
225 }
226 }
314 if (!active) 227 if (!active)
315 return 0; 228 return 0;
316 229
317 if (new_client->pwr_state == VGA_SWITCHEROO_OFF) 230 if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
318 vga_switchon(new_client); 231 vga_switchon(new_client);
319 232
320 vga_set_default_device(new_client->pdev); 233 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */
234 active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
235 new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
321 return 0; 236 return 0;
322} 237}
323 238
@@ -325,16 +240,20 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
325static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) 240static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
326{ 241{
327 int ret; 242 int ret;
328 struct vga_switcheroo_client *active; 243 int i;
244 struct vga_switcheroo_client *active = NULL;
329 245
330 active = find_active_client(&vgasr_priv.clients); 246 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
247 if (vgasr_priv.clients[i].active == true) {
248 active = &vgasr_priv.clients[i];
249 break;
250 }
251 }
331 if (!active) 252 if (!active)
332 return 0; 253 return 0;
333 254
334 active->active = false; 255 active->active = false;
335 256
336 set_audio_state(active->id, VGA_SWITCHEROO_OFF);
337
338 if (new_client->fb_info) { 257 if (new_client->fb_info) {
339 struct fb_event event; 258 struct fb_event event;
340 event.info = new_client->fb_info; 259 event.info = new_client->fb_info;
@@ -345,37 +264,23 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
345 if (ret) 264 if (ret)
346 return ret; 265 return ret;
347 266
348 if (new_client->ops->reprobe) 267 if (new_client->reprobe)
349 new_client->ops->reprobe(new_client->pdev); 268 new_client->reprobe(new_client->pdev);
350 269
351 if (active->pwr_state == VGA_SWITCHEROO_ON) 270 if (active->pwr_state == VGA_SWITCHEROO_ON)
352 vga_switchoff(active); 271 vga_switchoff(active);
353 272
354 set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
355
356 new_client->active = true; 273 new_client->active = true;
357 return 0; 274 return 0;
358} 275}
359 276
360static bool check_can_switch(void)
361{
362 struct vga_switcheroo_client *client;
363
364 list_for_each_entry(client, &vgasr_priv.clients, list) {
365 if (!client->ops->can_switch(client->pdev)) {
366 printk(KERN_ERR "vga_switcheroo: client %x refused switch\n", client->id);
367 return false;
368 }
369 }
370 return true;
371}
372
373static ssize_t 277static ssize_t
374vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, 278vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
375 size_t cnt, loff_t *ppos) 279 size_t cnt, loff_t *ppos)
376{ 280{
377 char usercmd[64]; 281 char usercmd[64];
378 int ret; 282 const char *pdev_name;
283 int i, ret;
379 bool delay = false, can_switch; 284 bool delay = false, can_switch;
380 bool just_mux = false; 285 bool just_mux = false;
381 int client_id = -1; 286 int client_id = -1;
@@ -396,23 +301,21 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
396 301
397 /* pwr off the device not in use */ 302 /* pwr off the device not in use */
398 if (strncmp(usercmd, "OFF", 3) == 0) { 303 if (strncmp(usercmd, "OFF", 3) == 0) {
399 list_for_each_entry(client, &vgasr_priv.clients, list) { 304 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
400 if (client->active || client_is_audio(client)) 305 if (vgasr_priv.clients[i].active)
401 continue; 306 continue;
402 set_audio_state(client->id, VGA_SWITCHEROO_OFF); 307 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON)
403 if (client->pwr_state == VGA_SWITCHEROO_ON) 308 vga_switchoff(&vgasr_priv.clients[i]);
404 vga_switchoff(client);
405 } 309 }
406 goto out; 310 goto out;
407 } 311 }
408 /* pwr on the device not in use */ 312 /* pwr on the device not in use */
409 if (strncmp(usercmd, "ON", 2) == 0) { 313 if (strncmp(usercmd, "ON", 2) == 0) {
410 list_for_each_entry(client, &vgasr_priv.clients, list) { 314 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
411 if (client->active || client_is_audio(client)) 315 if (vgasr_priv.clients[i].active)
412 continue; 316 continue;
413 if (client->pwr_state == VGA_SWITCHEROO_OFF) 317 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF)
414 vga_switchon(client); 318 vga_switchon(&vgasr_priv.clients[i]);
415 set_audio_state(client->id, VGA_SWITCHEROO_ON);
416 } 319 }
417 goto out; 320 goto out;
418 } 321 }
@@ -445,9 +348,13 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
445 348
446 if (client_id == -1) 349 if (client_id == -1)
447 goto out; 350 goto out;
448 client = find_client_from_id(&vgasr_priv.clients, client_id); 351
449 if (!client) 352 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
450 goto out; 353 if (vgasr_priv.clients[i].id == client_id) {
354 client = &vgasr_priv.clients[i];
355 break;
356 }
357 }
451 358
452 vgasr_priv.delayed_switch_active = false; 359 vgasr_priv.delayed_switch_active = false;
453 360
@@ -456,16 +363,24 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
456 goto out; 363 goto out;
457 } 364 }
458 365
459 if (client->active) 366 if (client->active == true)
460 goto out; 367 goto out;
461 368
462 /* okay we want a switch - test if devices are willing to switch */ 369 /* okay we want a switch - test if devices are willing to switch */
463 can_switch = check_can_switch(); 370 can_switch = true;
371 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
372 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
373 if (can_switch == false) {
374 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
375 break;
376 }
377 }
464 378
465 if (can_switch == false && delay == false) 379 if (can_switch == false && delay == false)
466 goto out; 380 goto out;
467 381
468 if (can_switch) { 382 if (can_switch == true) {
383 pdev_name = pci_name(client->pdev);
469 ret = vga_switchto_stage1(client); 384 ret = vga_switchto_stage1(client);
470 if (ret) 385 if (ret)
471 printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret); 386 printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
@@ -536,7 +451,10 @@ fail:
536 451
537int vga_switcheroo_process_delayed_switch(void) 452int vga_switcheroo_process_delayed_switch(void)
538{ 453{
539 struct vga_switcheroo_client *client; 454 struct vga_switcheroo_client *client = NULL;
455 const char *pdev_name;
456 bool can_switch = true;
457 int i;
540 int ret; 458 int ret;
541 int err = -EINVAL; 459 int err = -EINVAL;
542 460
@@ -546,11 +464,20 @@ int vga_switcheroo_process_delayed_switch(void)
546 464
547 printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id); 465 printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
548 466
549 client = find_client_from_id(&vgasr_priv.clients, 467 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
550 vgasr_priv.delayed_client_id); 468 if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id)
551 if (!client || !check_can_switch()) 469 client = &vgasr_priv.clients[i];
470 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
471 if (can_switch == false) {
472 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
473 break;
474 }
475 }
476
477 if (can_switch == false || client == NULL)
552 goto err; 478 goto err;
553 479
480 pdev_name = pci_name(client->pdev);
554 ret = vga_switchto_stage2(client); 481 ret = vga_switchto_stage2(client);
555 if (ret) 482 if (ret)
556 printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret); 483 printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
@@ -562,3 +489,4 @@ err:
562 return err; 489 return err;
563} 490}
564EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); 491EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
492
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index e893f6e1937..c72f1c0b5e6 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -136,17 +136,6 @@ struct pci_dev *vga_default_device(void)
136{ 136{
137 return vga_default; 137 return vga_default;
138} 138}
139
140EXPORT_SYMBOL_GPL(vga_default_device);
141
142void vga_set_default_device(struct pci_dev *pdev)
143{
144 if (vga_default == pdev)
145 return;
146
147 pci_dev_put(vga_default);
148 vga_default = pci_dev_get(pdev);
149}
150#endif 139#endif
151 140
152static inline void vga_irq_set_state(struct vga_device *vgadev, bool state) 141static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
@@ -476,29 +465,31 @@ static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
476 while (new_bus) { 465 while (new_bus) {
477 new_bridge = new_bus->self; 466 new_bridge = new_bus->self;
478 467
479 /* go through list of devices already registered */ 468 if (new_bridge) {
480 list_for_each_entry(same_bridge_vgadev, &vga_list, list) { 469 /* go through list of devices already registered */
481 bus = same_bridge_vgadev->pdev->bus; 470 list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
482 bridge = bus->self; 471 bus = same_bridge_vgadev->pdev->bus;
483
484 /* see if the share a bridge with this device */
485 if (new_bridge == bridge) {
486 /* if their direct parent bridge is the same
487 as any bridge of this device then it can't be used
488 for that device */
489 same_bridge_vgadev->bridge_has_one_vga = false;
490 }
491
492 /* now iterate the previous devices bridge hierarchy */
493 /* if the new devices parent bridge is in the other devices
494 hierarchy then we can't use it to control this device */
495 while (bus) {
496 bridge = bus->self; 472 bridge = bus->self;
497 if (bridge) { 473
498 if (bridge == vgadev->pdev->bus->self) 474 /* see if the share a bridge with this device */
499 vgadev->bridge_has_one_vga = false; 475 if (new_bridge == bridge) {
476 /* if their direct parent bridge is the same
477 as any bridge of this device then it can't be used
478 for that device */
479 same_bridge_vgadev->bridge_has_one_vga = false;
480 }
481
482 /* now iterate the previous devices bridge hierarchy */
483 /* if the new devices parent bridge is in the other devices
484 hierarchy then we can't use it to control this device */
485 while (bus) {
486 bridge = bus->self;
487 if (bridge) {
488 if (bridge == vgadev->pdev->bus->self)
489 vgadev->bridge_has_one_vga = false;
490 }
491 bus = bus->parent;
500 } 492 }
501 bus = bus->parent;
502 } 493 }
503 } 494 }
504 new_bus = new_bus->parent; 495 new_bus = new_bus->parent;
@@ -581,7 +572,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
581#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE 572#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
582 if (vga_default == NULL && 573 if (vga_default == NULL &&
583 ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) 574 ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
584 vga_set_default_device(pdev); 575 vga_default = pci_dev_get(pdev);
585#endif 576#endif
586 577
587 vga_arbiter_check_bridge_sharing(vgadev); 578 vga_arbiter_check_bridge_sharing(vgadev);
@@ -616,10 +607,10 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
616 goto bail; 607 goto bail;
617 } 608 }
618 609
619#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE 610 if (vga_default == pdev) {
620 if (vga_default == pdev) 611 pci_dev_put(vga_default);
621 vga_set_default_device(NULL); 612 vga_default = NULL;
622#endif 613 }
623 614
624 if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) 615 if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
625 vga_decode_count--; 616 vga_decode_count--;
@@ -1002,20 +993,14 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
1002 uc = &priv->cards[i]; 993 uc = &priv->cards[i];
1003 } 994 }
1004 995
1005 if (!uc) { 996 if (!uc)
1006 ret_val = -EINVAL; 997 return -EINVAL;
1007 goto done;
1008 }
1009 998
1010 if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) { 999 if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0)
1011 ret_val = -EINVAL; 1000 return -EINVAL;
1012 goto done;
1013 }
1014 1001
1015 if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) { 1002 if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0)
1016 ret_val = -EINVAL; 1003 return -EINVAL;
1017 goto done;
1018 }
1019 1004
1020 vga_put(pdev, io_state); 1005 vga_put(pdev, io_state);
1021 1006
@@ -1068,6 +1053,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
1068 } 1053 }
1069 1054
1070 } else if (strncmp(curr_pos, "target ", 7) == 0) { 1055 } else if (strncmp(curr_pos, "target ", 7) == 0) {
1056 struct pci_bus *pbus;
1071 unsigned int domain, bus, devfn; 1057 unsigned int domain, bus, devfn;
1072 struct vga_device *vgadev; 1058 struct vga_device *vgadev;
1073 1059
@@ -1086,11 +1072,19 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
1086 pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos, 1072 pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
1087 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1073 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
1088 1074
1089 pdev = pci_get_domain_bus_and_slot(domain, bus, devfn); 1075 pbus = pci_find_bus(domain, bus);
1076 pr_debug("vgaarb: pbus %p\n", pbus);
1077 if (pbus == NULL) {
1078 pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
1079 domain, bus);
1080 ret_val = -ENODEV;
1081 goto done;
1082 }
1083 pdev = pci_get_slot(pbus, devfn);
1090 pr_debug("vgaarb: pdev %p\n", pdev); 1084 pr_debug("vgaarb: pdev %p\n", pdev);
1091 if (!pdev) { 1085 if (!pdev) {
1092 pr_err("vgaarb: invalid PCI address %x:%x:%x\n", 1086 pr_err("vgaarb: invalid PCI address %x:%x\n",
1093 domain, bus, devfn); 1087 bus, devfn);
1094 ret_val = -ENODEV; 1088 ret_val = -ENODEV;
1095 goto done; 1089 goto done;
1096 } 1090 }