diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-16 10:49:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-16 10:49:54 -0400 |
commit | 4406c56d0a4da7a37b9180abeaece6cd00bcc874 (patch) | |
tree | 65a85fa73a25d24cbed6d163fdcf8df1b934a0be /drivers/gpu/vga | |
parent | 6b7b352f2102e21f9d8f38e932f01d9c5705c073 (diff) | |
parent | 5e3573db2bd5db6925159279d99576a4635bdb66 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (75 commits)
PCI hotplug: clean up acpi_run_hpp()
PCI hotplug: acpiphp: use generic pci_configure_slot()
PCI hotplug: shpchp: use generic pci_configure_slot()
PCI hotplug: pciehp: use generic pci_configure_slot()
PCI hotplug: add pci_configure_slot()
PCI hotplug: clean up acpi_get_hp_params_from_firmware() interface
PCI hotplug: acpiphp: don't cache hotplug_params in acpiphp_bridge
PCI hotplug: acpiphp: remove superfluous _HPP/_HPX evaluation
PCI: Clear saved_state after the state has been restored
PCI PM: Return error codes from pci_pm_resume()
PCI: use dev_printk in quirk messages
PCI / PCIe portdrv: Fix pcie_portdrv_slot_reset()
PCI Hotplug: convert acpi_pci_detect_ejectable() to take an acpi_handle
PCI Hotplug: acpiphp: find bridges the easy way
PCI: pcie portdrv: remove unused variable
PCI / ACPI PM: Propagate wake-up enable for devices w/o ACPI support
ACPI PM: Replace wakeup.prepared with reference counter
PCI PM: Introduce device flag wakeup_prepared
PCI / ACPI PM: Rework some debug messages
PCI PM: Simplify PCI wake-up code
...
Fixed up conflict in arch/powerpc/kernel/pci_64.c due to OF device tree
scanning having been moved and merged for the 32- and 64-bit cases. The
'needs_freset' initialization added in 6e19314cc ("PCI/powerpc: support
PCIe fundamental reset") is now in arch/powerpc/kernel/pci_of_scan.c.
Diffstat (limited to 'drivers/gpu/vga')
-rw-r--r-- | drivers/gpu/vga/Kconfig | 10 | ||||
-rw-r--r-- | drivers/gpu/vga/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/vga/vgaarb.c | 1205 |
3 files changed, 1216 insertions, 0 deletions
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig new file mode 100644 index 000000000000..790e675b13eb --- /dev/null +++ b/drivers/gpu/vga/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config VGA_ARB | ||
2 | bool "VGA Arbitration" if EMBEDDED | ||
3 | default y | ||
4 | depends on PCI | ||
5 | help | ||
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 | ||
8 | are accessed at same time they need some kind of coordination. Please | ||
9 | see Documentation/vgaarbiter.txt for more details. Select this to | ||
10 | enable VGA arbiter. | ||
diff --git a/drivers/gpu/vga/Makefile b/drivers/gpu/vga/Makefile new file mode 100644 index 000000000000..7cc8c1ed645b --- /dev/null +++ b/drivers/gpu/vga/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_VGA_ARB) += vgaarb.o | |||
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c new file mode 100644 index 000000000000..1ac0c93603c9 --- /dev/null +++ b/drivers/gpu/vga/vgaarb.c | |||
@@ -0,0 +1,1205 @@ | |||
1 | /* | ||
2 | * vgaarb.c | ||
3 | * | ||
4 | * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com> | ||
6 | * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org> | ||
7 | * | ||
8 | * Implements the VGA arbitration. For details refer to | ||
9 | * Documentation/vgaarbiter.txt | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/wait.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/poll.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | |||
24 | #include <linux/uaccess.h> | ||
25 | |||
26 | #include <linux/vgaarb.h> | ||
27 | |||
28 | static void vga_arbiter_notify_clients(void); | ||
29 | /* | ||
30 | * We keep a list of all vga devices in the system to speed | ||
31 | * up the various operations of the arbiter | ||
32 | */ | ||
33 | struct vga_device { | ||
34 | struct list_head list; | ||
35 | struct pci_dev *pdev; | ||
36 | unsigned int decodes; /* what does it decodes */ | ||
37 | unsigned int owns; /* what does it owns */ | ||
38 | unsigned int locks; /* what does it locks */ | ||
39 | unsigned int io_lock_cnt; /* legacy IO lock count */ | ||
40 | unsigned int mem_lock_cnt; /* legacy MEM lock count */ | ||
41 | unsigned int io_norm_cnt; /* normal IO count */ | ||
42 | unsigned int mem_norm_cnt; /* normal MEM count */ | ||
43 | |||
44 | /* allow IRQ enable/disable hook */ | ||
45 | void *cookie; | ||
46 | void (*irq_set_state)(void *cookie, bool enable); | ||
47 | unsigned int (*set_vga_decode)(void *cookie, bool decode); | ||
48 | }; | ||
49 | |||
50 | static LIST_HEAD(vga_list); | ||
51 | static int vga_count, vga_decode_count; | ||
52 | static bool vga_arbiter_used; | ||
53 | static DEFINE_SPINLOCK(vga_lock); | ||
54 | static DECLARE_WAIT_QUEUE_HEAD(vga_wait_queue); | ||
55 | |||
56 | |||
57 | static const char *vga_iostate_to_str(unsigned int iostate) | ||
58 | { | ||
59 | /* Ignore VGA_RSRC_IO and VGA_RSRC_MEM */ | ||
60 | iostate &= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; | ||
61 | switch (iostate) { | ||
62 | case VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM: | ||
63 | return "io+mem"; | ||
64 | case VGA_RSRC_LEGACY_IO: | ||
65 | return "io"; | ||
66 | case VGA_RSRC_LEGACY_MEM: | ||
67 | return "mem"; | ||
68 | } | ||
69 | return "none"; | ||
70 | } | ||
71 | |||
72 | static int vga_str_to_iostate(char *buf, int str_size, int *io_state) | ||
73 | { | ||
74 | /* we could in theory hand out locks on IO and mem | ||
75 | * separately to userspace but it can cause deadlocks */ | ||
76 | if (strncmp(buf, "none", 4) == 0) { | ||
77 | *io_state = VGA_RSRC_NONE; | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | /* XXX We're not chekcing the str_size! */ | ||
82 | if (strncmp(buf, "io+mem", 6) == 0) | ||
83 | goto both; | ||
84 | else if (strncmp(buf, "io", 2) == 0) | ||
85 | goto both; | ||
86 | else if (strncmp(buf, "mem", 3) == 0) | ||
87 | goto both; | ||
88 | return 0; | ||
89 | both: | ||
90 | *io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; | ||
91 | return 1; | ||
92 | } | ||
93 | |||
94 | #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE | ||
95 | /* this is only used a cookie - it should not be dereferenced */ | ||
96 | static struct pci_dev *vga_default; | ||
97 | #endif | ||
98 | |||
99 | static void vga_arb_device_card_gone(struct pci_dev *pdev); | ||
100 | |||
101 | /* Find somebody in our list */ | ||
102 | static struct vga_device *vgadev_find(struct pci_dev *pdev) | ||
103 | { | ||
104 | struct vga_device *vgadev; | ||
105 | |||
106 | list_for_each_entry(vgadev, &vga_list, list) | ||
107 | if (pdev == vgadev->pdev) | ||
108 | return vgadev; | ||
109 | return NULL; | ||
110 | } | ||
111 | |||
112 | /* Returns the default VGA device (vgacon's babe) */ | ||
113 | #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE | ||
114 | struct pci_dev *vga_default_device(void) | ||
115 | { | ||
116 | return vga_default; | ||
117 | } | ||
118 | #endif | ||
119 | |||
120 | static inline void vga_irq_set_state(struct vga_device *vgadev, bool state) | ||
121 | { | ||
122 | if (vgadev->irq_set_state) | ||
123 | vgadev->irq_set_state(vgadev->cookie, state); | ||
124 | } | ||
125 | |||
126 | |||
127 | /* If we don't ever use VGA arb we should avoid | ||
128 | turning off anything anywhere due to old X servers getting | ||
129 | confused about the boot device not being VGA */ | ||
130 | static void vga_check_first_use(void) | ||
131 | { | ||
132 | /* we should inform all GPUs in the system that | ||
133 | * VGA arb has occured and to try and disable resources | ||
134 | * if they can */ | ||
135 | if (!vga_arbiter_used) { | ||
136 | vga_arbiter_used = true; | ||
137 | vga_arbiter_notify_clients(); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static struct vga_device *__vga_tryget(struct vga_device *vgadev, | ||
142 | unsigned int rsrc) | ||
143 | { | ||
144 | unsigned int wants, legacy_wants, match; | ||
145 | struct vga_device *conflict; | ||
146 | unsigned int pci_bits; | ||
147 | /* Account for "normal" resources to lock. If we decode the legacy, | ||
148 | * counterpart, we need to request it as well | ||
149 | */ | ||
150 | if ((rsrc & VGA_RSRC_NORMAL_IO) && | ||
151 | (vgadev->decodes & VGA_RSRC_LEGACY_IO)) | ||
152 | rsrc |= VGA_RSRC_LEGACY_IO; | ||
153 | if ((rsrc & VGA_RSRC_NORMAL_MEM) && | ||
154 | (vgadev->decodes & VGA_RSRC_LEGACY_MEM)) | ||
155 | rsrc |= VGA_RSRC_LEGACY_MEM; | ||
156 | |||
157 | pr_devel("%s: %d\n", __func__, rsrc); | ||
158 | pr_devel("%s: owns: %d\n", __func__, vgadev->owns); | ||
159 | |||
160 | /* Check what resources we need to acquire */ | ||
161 | wants = rsrc & ~vgadev->owns; | ||
162 | |||
163 | /* We already own everything, just mark locked & bye bye */ | ||
164 | if (wants == 0) | ||
165 | goto lock_them; | ||
166 | |||
167 | /* We don't need to request a legacy resource, we just enable | ||
168 | * appropriate decoding and go | ||
169 | */ | ||
170 | legacy_wants = wants & VGA_RSRC_LEGACY_MASK; | ||
171 | if (legacy_wants == 0) | ||
172 | goto enable_them; | ||
173 | |||
174 | /* Ok, we don't, let's find out how we need to kick off */ | ||
175 | list_for_each_entry(conflict, &vga_list, list) { | ||
176 | unsigned int lwants = legacy_wants; | ||
177 | unsigned int change_bridge = 0; | ||
178 | |||
179 | /* Don't conflict with myself */ | ||
180 | if (vgadev == conflict) | ||
181 | continue; | ||
182 | |||
183 | /* Check if the architecture allows a conflict between those | ||
184 | * 2 devices or if they are on separate domains | ||
185 | */ | ||
186 | if (!vga_conflicts(vgadev->pdev, conflict->pdev)) | ||
187 | continue; | ||
188 | |||
189 | /* We have a possible conflict. before we go further, we must | ||
190 | * check if we sit on the same bus as the conflicting device. | ||
191 | * if we don't, then we must tie both IO and MEM resources | ||
192 | * together since there is only a single bit controlling | ||
193 | * VGA forwarding on P2P bridges | ||
194 | */ | ||
195 | if (vgadev->pdev->bus != conflict->pdev->bus) { | ||
196 | change_bridge = 1; | ||
197 | lwants = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; | ||
198 | } | ||
199 | |||
200 | /* Check if the guy has a lock on the resource. If he does, | ||
201 | * return the conflicting entry | ||
202 | */ | ||
203 | if (conflict->locks & lwants) | ||
204 | return conflict; | ||
205 | |||
206 | /* Ok, now check if he owns the resource we want. We don't need | ||
207 | * to check "decodes" since it should be impossible to own | ||
208 | * own legacy resources you don't decode unless I have a bug | ||
209 | * in this code... | ||
210 | */ | ||
211 | WARN_ON(conflict->owns & ~conflict->decodes); | ||
212 | match = lwants & conflict->owns; | ||
213 | if (!match) | ||
214 | continue; | ||
215 | |||
216 | /* looks like he doesn't have a lock, we can steal | ||
217 | * them from him | ||
218 | */ | ||
219 | vga_irq_set_state(conflict, false); | ||
220 | |||
221 | pci_bits = 0; | ||
222 | if (lwants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM)) | ||
223 | pci_bits |= PCI_COMMAND_MEMORY; | ||
224 | if (lwants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) | ||
225 | pci_bits |= PCI_COMMAND_IO; | ||
226 | |||
227 | pci_set_vga_state(conflict->pdev, false, pci_bits, | ||
228 | change_bridge); | ||
229 | conflict->owns &= ~lwants; | ||
230 | /* If he also owned non-legacy, that is no longer the case */ | ||
231 | if (lwants & VGA_RSRC_LEGACY_MEM) | ||
232 | conflict->owns &= ~VGA_RSRC_NORMAL_MEM; | ||
233 | if (lwants & VGA_RSRC_LEGACY_IO) | ||
234 | conflict->owns &= ~VGA_RSRC_NORMAL_IO; | ||
235 | } | ||
236 | |||
237 | enable_them: | ||
238 | /* ok dude, we got it, everybody conflicting has been disabled, let's | ||
239 | * enable us. Make sure we don't mark a bit in "owns" that we don't | ||
240 | * also have in "decodes". We can lock resources we don't decode but | ||
241 | * not own them. | ||
242 | */ | ||
243 | pci_bits = 0; | ||
244 | if (wants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM)) | ||
245 | pci_bits |= PCI_COMMAND_MEMORY; | ||
246 | if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) | ||
247 | pci_bits |= PCI_COMMAND_IO; | ||
248 | pci_set_vga_state(vgadev->pdev, true, pci_bits, !!(wants & VGA_RSRC_LEGACY_MASK)); | ||
249 | |||
250 | vga_irq_set_state(vgadev, true); | ||
251 | vgadev->owns |= (wants & vgadev->decodes); | ||
252 | lock_them: | ||
253 | vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK); | ||
254 | if (rsrc & VGA_RSRC_LEGACY_IO) | ||
255 | vgadev->io_lock_cnt++; | ||
256 | if (rsrc & VGA_RSRC_LEGACY_MEM) | ||
257 | vgadev->mem_lock_cnt++; | ||
258 | if (rsrc & VGA_RSRC_NORMAL_IO) | ||
259 | vgadev->io_norm_cnt++; | ||
260 | if (rsrc & VGA_RSRC_NORMAL_MEM) | ||
261 | vgadev->mem_norm_cnt++; | ||
262 | |||
263 | return NULL; | ||
264 | } | ||
265 | |||
266 | static void __vga_put(struct vga_device *vgadev, unsigned int rsrc) | ||
267 | { | ||
268 | unsigned int old_locks = vgadev->locks; | ||
269 | |||
270 | pr_devel("%s\n", __func__); | ||
271 | |||
272 | /* Update our counters, and account for equivalent legacy resources | ||
273 | * if we decode them | ||
274 | */ | ||
275 | if ((rsrc & VGA_RSRC_NORMAL_IO) && vgadev->io_norm_cnt > 0) { | ||
276 | vgadev->io_norm_cnt--; | ||
277 | if (vgadev->decodes & VGA_RSRC_LEGACY_IO) | ||
278 | rsrc |= VGA_RSRC_LEGACY_IO; | ||
279 | } | ||
280 | if ((rsrc & VGA_RSRC_NORMAL_MEM) && vgadev->mem_norm_cnt > 0) { | ||
281 | vgadev->mem_norm_cnt--; | ||
282 | if (vgadev->decodes & VGA_RSRC_LEGACY_MEM) | ||
283 | rsrc |= VGA_RSRC_LEGACY_MEM; | ||
284 | } | ||
285 | if ((rsrc & VGA_RSRC_LEGACY_IO) && vgadev->io_lock_cnt > 0) | ||
286 | vgadev->io_lock_cnt--; | ||
287 | if ((rsrc & VGA_RSRC_LEGACY_MEM) && vgadev->mem_lock_cnt > 0) | ||
288 | vgadev->mem_lock_cnt--; | ||
289 | |||
290 | /* Just clear lock bits, we do lazy operations so we don't really | ||
291 | * have to bother about anything else at this point | ||
292 | */ | ||
293 | if (vgadev->io_lock_cnt == 0) | ||
294 | vgadev->locks &= ~VGA_RSRC_LEGACY_IO; | ||
295 | if (vgadev->mem_lock_cnt == 0) | ||
296 | vgadev->locks &= ~VGA_RSRC_LEGACY_MEM; | ||
297 | |||
298 | /* Kick the wait queue in case somebody was waiting if we actually | ||
299 | * released something | ||
300 | */ | ||
301 | if (old_locks != vgadev->locks) | ||
302 | wake_up_all(&vga_wait_queue); | ||
303 | } | ||
304 | |||
305 | int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) | ||
306 | { | ||
307 | struct vga_device *vgadev, *conflict; | ||
308 | unsigned long flags; | ||
309 | wait_queue_t wait; | ||
310 | int rc = 0; | ||
311 | |||
312 | vga_check_first_use(); | ||
313 | /* The one who calls us should check for this, but lets be sure... */ | ||
314 | if (pdev == NULL) | ||
315 | pdev = vga_default_device(); | ||
316 | if (pdev == NULL) | ||
317 | return 0; | ||
318 | |||
319 | for (;;) { | ||
320 | spin_lock_irqsave(&vga_lock, flags); | ||
321 | vgadev = vgadev_find(pdev); | ||
322 | if (vgadev == NULL) { | ||
323 | spin_unlock_irqrestore(&vga_lock, flags); | ||
324 | rc = -ENODEV; | ||
325 | break; | ||
326 | } | ||
327 | conflict = __vga_tryget(vgadev, rsrc); | ||
328 | spin_unlock_irqrestore(&vga_lock, flags); | ||
329 | if (conflict == NULL) | ||
330 | break; | ||
331 | |||
332 | |||
333 | /* We have a conflict, we wait until somebody kicks the | ||
334 | * work queue. Currently we have one work queue that we | ||
335 | * kick each time some resources are released, but it would | ||
336 | * be fairly easy to have a per device one so that we only | ||
337 | * need to attach to the conflicting device | ||
338 | */ | ||
339 | init_waitqueue_entry(&wait, current); | ||
340 | add_wait_queue(&vga_wait_queue, &wait); | ||
341 | set_current_state(interruptible ? | ||
342 | TASK_INTERRUPTIBLE : | ||
343 | TASK_UNINTERRUPTIBLE); | ||
344 | if (signal_pending(current)) { | ||
345 | rc = -EINTR; | ||
346 | break; | ||
347 | } | ||
348 | schedule(); | ||
349 | remove_wait_queue(&vga_wait_queue, &wait); | ||
350 | set_current_state(TASK_RUNNING); | ||
351 | } | ||
352 | return rc; | ||
353 | } | ||
354 | EXPORT_SYMBOL(vga_get); | ||
355 | |||
356 | int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) | ||
357 | { | ||
358 | struct vga_device *vgadev; | ||
359 | unsigned long flags; | ||
360 | int rc = 0; | ||
361 | |||
362 | vga_check_first_use(); | ||
363 | |||
364 | /* The one who calls us should check for this, but lets be sure... */ | ||
365 | if (pdev == NULL) | ||
366 | pdev = vga_default_device(); | ||
367 | if (pdev == NULL) | ||
368 | return 0; | ||
369 | spin_lock_irqsave(&vga_lock, flags); | ||
370 | vgadev = vgadev_find(pdev); | ||
371 | if (vgadev == NULL) { | ||
372 | rc = -ENODEV; | ||
373 | goto bail; | ||
374 | } | ||
375 | if (__vga_tryget(vgadev, rsrc)) | ||
376 | rc = -EBUSY; | ||
377 | bail: | ||
378 | spin_unlock_irqrestore(&vga_lock, flags); | ||
379 | return rc; | ||
380 | } | ||
381 | EXPORT_SYMBOL(vga_tryget); | ||
382 | |||
383 | void vga_put(struct pci_dev *pdev, unsigned int rsrc) | ||
384 | { | ||
385 | struct vga_device *vgadev; | ||
386 | unsigned long flags; | ||
387 | |||
388 | /* The one who calls us should check for this, but lets be sure... */ | ||
389 | if (pdev == NULL) | ||
390 | pdev = vga_default_device(); | ||
391 | if (pdev == NULL) | ||
392 | return; | ||
393 | spin_lock_irqsave(&vga_lock, flags); | ||
394 | vgadev = vgadev_find(pdev); | ||
395 | if (vgadev == NULL) | ||
396 | goto bail; | ||
397 | __vga_put(vgadev, rsrc); | ||
398 | bail: | ||
399 | spin_unlock_irqrestore(&vga_lock, flags); | ||
400 | } | ||
401 | EXPORT_SYMBOL(vga_put); | ||
402 | |||
403 | /* | ||
404 | * Currently, we assume that the "initial" setup of the system is | ||
405 | * not sane, that is we come up with conflicting devices and let | ||
406 | * the arbiter's client decides if devices decodes or not legacy | ||
407 | * things. | ||
408 | */ | ||
409 | static bool vga_arbiter_add_pci_device(struct pci_dev *pdev) | ||
410 | { | ||
411 | struct vga_device *vgadev; | ||
412 | unsigned long flags; | ||
413 | struct pci_bus *bus; | ||
414 | struct pci_dev *bridge; | ||
415 | u16 cmd; | ||
416 | |||
417 | /* Only deal with VGA class devices */ | ||
418 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
419 | return false; | ||
420 | |||
421 | /* Allocate structure */ | ||
422 | vgadev = kmalloc(sizeof(struct vga_device), GFP_KERNEL); | ||
423 | if (vgadev == NULL) { | ||
424 | pr_err("vgaarb: failed to allocate pci device\n"); | ||
425 | /* What to do on allocation failure ? For now, let's | ||
426 | * just do nothing, I'm not sure there is anything saner | ||
427 | * to be done | ||
428 | */ | ||
429 | return false; | ||
430 | } | ||
431 | |||
432 | memset(vgadev, 0, sizeof(*vgadev)); | ||
433 | |||
434 | /* Take lock & check for duplicates */ | ||
435 | spin_lock_irqsave(&vga_lock, flags); | ||
436 | if (vgadev_find(pdev) != NULL) { | ||
437 | BUG_ON(1); | ||
438 | goto fail; | ||
439 | } | ||
440 | vgadev->pdev = pdev; | ||
441 | |||
442 | /* By default, assume we decode everything */ | ||
443 | vgadev->decodes = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | ||
444 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | ||
445 | |||
446 | /* by default mark it as decoding */ | ||
447 | vga_decode_count++; | ||
448 | /* Mark that we "own" resources based on our enables, we will | ||
449 | * clear that below if the bridge isn't forwarding | ||
450 | */ | ||
451 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); | ||
452 | if (cmd & PCI_COMMAND_IO) | ||
453 | vgadev->owns |= VGA_RSRC_LEGACY_IO; | ||
454 | if (cmd & PCI_COMMAND_MEMORY) | ||
455 | vgadev->owns |= VGA_RSRC_LEGACY_MEM; | ||
456 | |||
457 | /* Check if VGA cycles can get down to us */ | ||
458 | bus = pdev->bus; | ||
459 | while (bus) { | ||
460 | bridge = bus->self; | ||
461 | if (bridge) { | ||
462 | u16 l; | ||
463 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
464 | &l); | ||
465 | if (!(l & PCI_BRIDGE_CTL_VGA)) { | ||
466 | vgadev->owns = 0; | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | bus = bus->parent; | ||
471 | } | ||
472 | |||
473 | /* Deal with VGA default device. Use first enabled one | ||
474 | * by default if arch doesn't have it's own hook | ||
475 | */ | ||
476 | #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE | ||
477 | if (vga_default == NULL && | ||
478 | ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) | ||
479 | vga_default = pci_dev_get(pdev); | ||
480 | #endif | ||
481 | |||
482 | /* Add to the list */ | ||
483 | list_add(&vgadev->list, &vga_list); | ||
484 | vga_count++; | ||
485 | pr_info("vgaarb: device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n", | ||
486 | pci_name(pdev), | ||
487 | vga_iostate_to_str(vgadev->decodes), | ||
488 | vga_iostate_to_str(vgadev->owns), | ||
489 | vga_iostate_to_str(vgadev->locks)); | ||
490 | |||
491 | spin_unlock_irqrestore(&vga_lock, flags); | ||
492 | return true; | ||
493 | fail: | ||
494 | spin_unlock_irqrestore(&vga_lock, flags); | ||
495 | kfree(vgadev); | ||
496 | return false; | ||
497 | } | ||
498 | |||
499 | static bool vga_arbiter_del_pci_device(struct pci_dev *pdev) | ||
500 | { | ||
501 | struct vga_device *vgadev; | ||
502 | unsigned long flags; | ||
503 | bool ret = true; | ||
504 | |||
505 | spin_lock_irqsave(&vga_lock, flags); | ||
506 | vgadev = vgadev_find(pdev); | ||
507 | if (vgadev == NULL) { | ||
508 | ret = false; | ||
509 | goto bail; | ||
510 | } | ||
511 | |||
512 | if (vga_default == pdev) { | ||
513 | pci_dev_put(vga_default); | ||
514 | vga_default = NULL; | ||
515 | } | ||
516 | |||
517 | if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) | ||
518 | vga_decode_count--; | ||
519 | |||
520 | /* Remove entry from list */ | ||
521 | list_del(&vgadev->list); | ||
522 | vga_count--; | ||
523 | /* Notify userland driver that the device is gone so it discards | ||
524 | * it's copies of the pci_dev pointer | ||
525 | */ | ||
526 | vga_arb_device_card_gone(pdev); | ||
527 | |||
528 | /* Wake up all possible waiters */ | ||
529 | wake_up_all(&vga_wait_queue); | ||
530 | bail: | ||
531 | spin_unlock_irqrestore(&vga_lock, flags); | ||
532 | kfree(vgadev); | ||
533 | return ret; | ||
534 | } | ||
535 | |||
536 | /* this is called with the lock */ | ||
537 | static inline void vga_update_device_decodes(struct vga_device *vgadev, | ||
538 | int new_decodes) | ||
539 | { | ||
540 | int old_decodes; | ||
541 | struct vga_device *new_vgadev, *conflict; | ||
542 | |||
543 | old_decodes = vgadev->decodes; | ||
544 | vgadev->decodes = new_decodes; | ||
545 | |||
546 | pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n", | ||
547 | pci_name(vgadev->pdev), | ||
548 | vga_iostate_to_str(old_decodes), | ||
549 | vga_iostate_to_str(vgadev->decodes), | ||
550 | vga_iostate_to_str(vgadev->owns)); | ||
551 | |||
552 | |||
553 | /* if we own the decodes we should move them along to | ||
554 | another card */ | ||
555 | if ((vgadev->owns & old_decodes) && (vga_count > 1)) { | ||
556 | /* set us to own nothing */ | ||
557 | vgadev->owns &= ~old_decodes; | ||
558 | list_for_each_entry(new_vgadev, &vga_list, list) { | ||
559 | if ((new_vgadev != vgadev) && | ||
560 | (new_vgadev->decodes & VGA_RSRC_LEGACY_MASK)) { | ||
561 | pr_info("vgaarb: transferring owner from PCI:%s to PCI:%s\n", pci_name(vgadev->pdev), pci_name(new_vgadev->pdev)); | ||
562 | conflict = __vga_tryget(new_vgadev, VGA_RSRC_LEGACY_MASK); | ||
563 | if (!conflict) | ||
564 | __vga_put(new_vgadev, VGA_RSRC_LEGACY_MASK); | ||
565 | break; | ||
566 | } | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* change decodes counter */ | ||
571 | if (old_decodes != new_decodes) { | ||
572 | if (new_decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) | ||
573 | vga_decode_count++; | ||
574 | else | ||
575 | vga_decode_count--; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) | ||
580 | { | ||
581 | struct vga_device *vgadev; | ||
582 | unsigned long flags; | ||
583 | |||
584 | decodes &= VGA_RSRC_LEGACY_MASK; | ||
585 | |||
586 | spin_lock_irqsave(&vga_lock, flags); | ||
587 | vgadev = vgadev_find(pdev); | ||
588 | if (vgadev == NULL) | ||
589 | goto bail; | ||
590 | |||
591 | /* don't let userspace futz with kernel driver decodes */ | ||
592 | if (userspace && vgadev->set_vga_decode) | ||
593 | goto bail; | ||
594 | |||
595 | /* update the device decodes + counter */ | ||
596 | vga_update_device_decodes(vgadev, decodes); | ||
597 | |||
598 | /* XXX if somebody is going from "doesn't decode" to "decodes" state | ||
599 | * here, additional care must be taken as we may have pending owner | ||
600 | * ship of non-legacy region ... | ||
601 | */ | ||
602 | bail: | ||
603 | spin_unlock_irqrestore(&vga_lock, flags); | ||
604 | } | ||
605 | |||
606 | void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes) | ||
607 | { | ||
608 | __vga_set_legacy_decoding(pdev, decodes, false); | ||
609 | } | ||
610 | EXPORT_SYMBOL(vga_set_legacy_decoding); | ||
611 | |||
612 | /* call with NULL to unregister */ | ||
613 | int vga_client_register(struct pci_dev *pdev, void *cookie, | ||
614 | void (*irq_set_state)(void *cookie, bool state), | ||
615 | unsigned int (*set_vga_decode)(void *cookie, bool decode)) | ||
616 | { | ||
617 | int ret = -1; | ||
618 | struct vga_device *vgadev; | ||
619 | unsigned long flags; | ||
620 | |||
621 | spin_lock_irqsave(&vga_lock, flags); | ||
622 | vgadev = vgadev_find(pdev); | ||
623 | if (!vgadev) | ||
624 | goto bail; | ||
625 | |||
626 | vgadev->irq_set_state = irq_set_state; | ||
627 | vgadev->set_vga_decode = set_vga_decode; | ||
628 | vgadev->cookie = cookie; | ||
629 | ret = 0; | ||
630 | |||
631 | bail: | ||
632 | spin_unlock_irqrestore(&vga_lock, flags); | ||
633 | return ret; | ||
634 | |||
635 | } | ||
636 | EXPORT_SYMBOL(vga_client_register); | ||
637 | |||
638 | /* | ||
639 | * Char driver implementation | ||
640 | * | ||
641 | * Semantics is: | ||
642 | * | ||
643 | * open : open user instance of the arbitrer. by default, it's | ||
644 | * attached to the default VGA device of the system. | ||
645 | * | ||
646 | * close : close user instance, release locks | ||
647 | * | ||
648 | * read : return a string indicating the status of the target. | ||
649 | * an IO state string is of the form {io,mem,io+mem,none}, | ||
650 | * mc and ic are respectively mem and io lock counts (for | ||
651 | * debugging/diagnostic only). "decodes" indicate what the | ||
652 | * card currently decodes, "owns" indicates what is currently | ||
653 | * enabled on it, and "locks" indicates what is locked by this | ||
654 | * card. If the card is unplugged, we get "invalid" then for | ||
655 | * card_ID and an -ENODEV error is returned for any command | ||
656 | * until a new card is targeted | ||
657 | * | ||
658 | * "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)" | ||
659 | * | ||
660 | * write : write a command to the arbiter. List of commands is: | ||
661 | * | ||
662 | * target <card_ID> : switch target to card <card_ID> (see below) | ||
663 | * lock <io_state> : acquires locks on target ("none" is invalid io_state) | ||
664 | * trylock <io_state> : non-blocking acquire locks on target | ||
665 | * unlock <io_state> : release locks on target | ||
666 | * unlock all : release all locks on target held by this user | ||
667 | * decodes <io_state> : set the legacy decoding attributes for the card | ||
668 | * | ||
669 | * poll : event if something change on any card (not just the target) | ||
670 | * | ||
671 | * card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default" | ||
672 | * to go back to the system default card (TODO: not implemented yet). | ||
673 | * Currently, only PCI is supported as a prefix, but the userland API may | ||
674 | * support other bus types in the future, even if the current kernel | ||
675 | * implementation doesn't. | ||
676 | * | ||
677 | * Note about locks: | ||
678 | * | ||
679 | * The driver keeps track of which user has what locks on which card. It | ||
680 | * supports stacking, like the kernel one. This complexifies the implementation | ||
681 | * a bit, but makes the arbiter more tolerant to userspace problems and able | ||
682 | * to properly cleanup in all cases when a process dies. | ||
683 | * Currently, a max of 16 cards simultaneously can have locks issued from | ||
684 | * userspace for a given user (file descriptor instance) of the arbiter. | ||
685 | * | ||
686 | * If the device is hot-unplugged, there is a hook inside the module to notify | ||
687 | * they being added/removed in the system and automatically added/removed in | ||
688 | * the arbiter. | ||
689 | */ | ||
690 | |||
691 | #define MAX_USER_CARDS 16 | ||
692 | #define PCI_INVALID_CARD ((struct pci_dev *)-1UL) | ||
693 | |||
694 | /* | ||
695 | * Each user has an array of these, tracking which cards have locks | ||
696 | */ | ||
697 | struct vga_arb_user_card { | ||
698 | struct pci_dev *pdev; | ||
699 | unsigned int mem_cnt; | ||
700 | unsigned int io_cnt; | ||
701 | }; | ||
702 | |||
703 | struct vga_arb_private { | ||
704 | struct list_head list; | ||
705 | struct pci_dev *target; | ||
706 | struct vga_arb_user_card cards[MAX_USER_CARDS]; | ||
707 | spinlock_t lock; | ||
708 | }; | ||
709 | |||
710 | static LIST_HEAD(vga_user_list); | ||
711 | static DEFINE_SPINLOCK(vga_user_lock); | ||
712 | |||
713 | |||
714 | /* | ||
715 | * This function gets a string in the format: "PCI:domain:bus:dev.fn" and | ||
716 | * returns the respective values. If the string is not in this format, | ||
717 | * it returns 0. | ||
718 | */ | ||
719 | static int vga_pci_str_to_vars(char *buf, int count, unsigned int *domain, | ||
720 | unsigned int *bus, unsigned int *devfn) | ||
721 | { | ||
722 | int n; | ||
723 | unsigned int slot, func; | ||
724 | |||
725 | |||
726 | n = sscanf(buf, "PCI:%x:%x:%x.%x", domain, bus, &slot, &func); | ||
727 | if (n != 4) | ||
728 | return 0; | ||
729 | |||
730 | *devfn = PCI_DEVFN(slot, func); | ||
731 | |||
732 | return 1; | ||
733 | } | ||
734 | |||
735 | static ssize_t vga_arb_read(struct file *file, char __user * buf, | ||
736 | size_t count, loff_t *ppos) | ||
737 | { | ||
738 | struct vga_arb_private *priv = file->private_data; | ||
739 | struct vga_device *vgadev; | ||
740 | struct pci_dev *pdev; | ||
741 | unsigned long flags; | ||
742 | size_t len; | ||
743 | int rc; | ||
744 | char *lbuf; | ||
745 | |||
746 | lbuf = kmalloc(1024, GFP_KERNEL); | ||
747 | if (lbuf == NULL) | ||
748 | return -ENOMEM; | ||
749 | |||
750 | /* Shields against vga_arb_device_card_gone (pci_dev going | ||
751 | * away), and allows access to vga list | ||
752 | */ | ||
753 | spin_lock_irqsave(&vga_lock, flags); | ||
754 | |||
755 | /* If we are targetting the default, use it */ | ||
756 | pdev = priv->target; | ||
757 | if (pdev == NULL || pdev == PCI_INVALID_CARD) { | ||
758 | spin_unlock_irqrestore(&vga_lock, flags); | ||
759 | len = sprintf(lbuf, "invalid"); | ||
760 | goto done; | ||
761 | } | ||
762 | |||
763 | /* Find card vgadev structure */ | ||
764 | vgadev = vgadev_find(pdev); | ||
765 | if (vgadev == NULL) { | ||
766 | /* Wow, it's not in the list, that shouldn't happen, | ||
767 | * let's fix us up and return invalid card | ||
768 | */ | ||
769 | if (pdev == priv->target) | ||
770 | vga_arb_device_card_gone(pdev); | ||
771 | spin_unlock_irqrestore(&vga_lock, flags); | ||
772 | len = sprintf(lbuf, "invalid"); | ||
773 | goto done; | ||
774 | } | ||
775 | |||
776 | /* Fill the buffer with infos */ | ||
777 | len = snprintf(lbuf, 1024, | ||
778 | "count:%d,PCI:%s,decodes=%s,owns=%s,locks=%s(%d:%d)\n", | ||
779 | vga_decode_count, pci_name(pdev), | ||
780 | vga_iostate_to_str(vgadev->decodes), | ||
781 | vga_iostate_to_str(vgadev->owns), | ||
782 | vga_iostate_to_str(vgadev->locks), | ||
783 | vgadev->io_lock_cnt, vgadev->mem_lock_cnt); | ||
784 | |||
785 | spin_unlock_irqrestore(&vga_lock, flags); | ||
786 | done: | ||
787 | |||
788 | /* Copy that to user */ | ||
789 | if (len > count) | ||
790 | len = count; | ||
791 | rc = copy_to_user(buf, lbuf, len); | ||
792 | kfree(lbuf); | ||
793 | if (rc) | ||
794 | return -EFAULT; | ||
795 | return len; | ||
796 | } | ||
797 | |||
798 | /* | ||
799 | * TODO: To avoid parsing inside kernel and to improve the speed we may | ||
800 | * consider use ioctl here | ||
801 | */ | ||
802 | static ssize_t vga_arb_write(struct file *file, const char __user * buf, | ||
803 | size_t count, loff_t *ppos) | ||
804 | { | ||
805 | struct vga_arb_private *priv = file->private_data; | ||
806 | struct vga_arb_user_card *uc = NULL; | ||
807 | struct pci_dev *pdev; | ||
808 | |||
809 | unsigned int io_state; | ||
810 | |||
811 | char *kbuf, *curr_pos; | ||
812 | size_t remaining = count; | ||
813 | |||
814 | int ret_val; | ||
815 | int i; | ||
816 | |||
817 | |||
818 | kbuf = kmalloc(count + 1, GFP_KERNEL); | ||
819 | if (!kbuf) | ||
820 | return -ENOMEM; | ||
821 | |||
822 | if (copy_from_user(kbuf, buf, count)) { | ||
823 | kfree(kbuf); | ||
824 | return -EFAULT; | ||
825 | } | ||
826 | curr_pos = kbuf; | ||
827 | kbuf[count] = '\0'; /* Just to make sure... */ | ||
828 | |||
829 | if (strncmp(curr_pos, "lock ", 5) == 0) { | ||
830 | curr_pos += 5; | ||
831 | remaining -= 5; | ||
832 | |||
833 | pr_devel("client 0x%p called 'lock'\n", priv); | ||
834 | |||
835 | if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { | ||
836 | ret_val = -EPROTO; | ||
837 | goto done; | ||
838 | } | ||
839 | if (io_state == VGA_RSRC_NONE) { | ||
840 | ret_val = -EPROTO; | ||
841 | goto done; | ||
842 | } | ||
843 | |||
844 | pdev = priv->target; | ||
845 | if (priv->target == NULL) { | ||
846 | ret_val = -ENODEV; | ||
847 | goto done; | ||
848 | } | ||
849 | |||
850 | vga_get_uninterruptible(pdev, io_state); | ||
851 | |||
852 | /* Update the client's locks lists... */ | ||
853 | for (i = 0; i < MAX_USER_CARDS; i++) { | ||
854 | if (priv->cards[i].pdev == pdev) { | ||
855 | if (io_state & VGA_RSRC_LEGACY_IO) | ||
856 | priv->cards[i].io_cnt++; | ||
857 | if (io_state & VGA_RSRC_LEGACY_MEM) | ||
858 | priv->cards[i].mem_cnt++; | ||
859 | break; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | ret_val = count; | ||
864 | goto done; | ||
865 | } else if (strncmp(curr_pos, "unlock ", 7) == 0) { | ||
866 | curr_pos += 7; | ||
867 | remaining -= 7; | ||
868 | |||
869 | pr_devel("client 0x%p called 'unlock'\n", priv); | ||
870 | |||
871 | if (strncmp(curr_pos, "all", 3) == 0) | ||
872 | io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; | ||
873 | else { | ||
874 | if (!vga_str_to_iostate | ||
875 | (curr_pos, remaining, &io_state)) { | ||
876 | ret_val = -EPROTO; | ||
877 | goto done; | ||
878 | } | ||
879 | /* TODO: Add this? | ||
880 | if (io_state == VGA_RSRC_NONE) { | ||
881 | ret_val = -EPROTO; | ||
882 | goto done; | ||
883 | } | ||
884 | */ | ||
885 | } | ||
886 | |||
887 | pdev = priv->target; | ||
888 | if (priv->target == NULL) { | ||
889 | ret_val = -ENODEV; | ||
890 | goto done; | ||
891 | } | ||
892 | for (i = 0; i < MAX_USER_CARDS; i++) { | ||
893 | if (priv->cards[i].pdev == pdev) | ||
894 | uc = &priv->cards[i]; | ||
895 | } | ||
896 | |||
897 | if (!uc) | ||
898 | return -EINVAL; | ||
899 | |||
900 | if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) | ||
901 | return -EINVAL; | ||
902 | |||
903 | if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) | ||
904 | return -EINVAL; | ||
905 | |||
906 | vga_put(pdev, io_state); | ||
907 | |||
908 | if (io_state & VGA_RSRC_LEGACY_IO) | ||
909 | uc->io_cnt--; | ||
910 | if (io_state & VGA_RSRC_LEGACY_MEM) | ||
911 | uc->mem_cnt--; | ||
912 | |||
913 | ret_val = count; | ||
914 | goto done; | ||
915 | } else if (strncmp(curr_pos, "trylock ", 8) == 0) { | ||
916 | curr_pos += 8; | ||
917 | remaining -= 8; | ||
918 | |||
919 | pr_devel("client 0x%p called 'trylock'\n", priv); | ||
920 | |||
921 | if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { | ||
922 | ret_val = -EPROTO; | ||
923 | goto done; | ||
924 | } | ||
925 | /* TODO: Add this? | ||
926 | if (io_state == VGA_RSRC_NONE) { | ||
927 | ret_val = -EPROTO; | ||
928 | goto done; | ||
929 | } | ||
930 | */ | ||
931 | |||
932 | pdev = priv->target; | ||
933 | if (priv->target == NULL) { | ||
934 | ret_val = -ENODEV; | ||
935 | goto done; | ||
936 | } | ||
937 | |||
938 | if (vga_tryget(pdev, io_state)) { | ||
939 | /* Update the client's locks lists... */ | ||
940 | for (i = 0; i < MAX_USER_CARDS; i++) { | ||
941 | if (priv->cards[i].pdev == pdev) { | ||
942 | if (io_state & VGA_RSRC_LEGACY_IO) | ||
943 | priv->cards[i].io_cnt++; | ||
944 | if (io_state & VGA_RSRC_LEGACY_MEM) | ||
945 | priv->cards[i].mem_cnt++; | ||
946 | break; | ||
947 | } | ||
948 | } | ||
949 | ret_val = count; | ||
950 | goto done; | ||
951 | } else { | ||
952 | ret_val = -EBUSY; | ||
953 | goto done; | ||
954 | } | ||
955 | |||
956 | } else if (strncmp(curr_pos, "target ", 7) == 0) { | ||
957 | unsigned int domain, bus, devfn; | ||
958 | struct vga_device *vgadev; | ||
959 | |||
960 | curr_pos += 7; | ||
961 | remaining -= 7; | ||
962 | pr_devel("client 0x%p called 'target'\n", priv); | ||
963 | /* if target is default */ | ||
964 | if (!strncmp(buf, "default", 7)) | ||
965 | pdev = pci_dev_get(vga_default_device()); | ||
966 | else { | ||
967 | if (!vga_pci_str_to_vars(curr_pos, remaining, | ||
968 | &domain, &bus, &devfn)) { | ||
969 | ret_val = -EPROTO; | ||
970 | goto done; | ||
971 | } | ||
972 | |||
973 | pdev = pci_get_bus_and_slot(bus, devfn); | ||
974 | if (!pdev) { | ||
975 | pr_info("vgaarb: invalid PCI address!\n"); | ||
976 | ret_val = -ENODEV; | ||
977 | goto done; | ||
978 | } | ||
979 | } | ||
980 | |||
981 | vgadev = vgadev_find(pdev); | ||
982 | if (vgadev == NULL) { | ||
983 | pr_info("vgaarb: this pci device is not a vga device\n"); | ||
984 | pci_dev_put(pdev); | ||
985 | ret_val = -ENODEV; | ||
986 | goto done; | ||
987 | } | ||
988 | |||
989 | priv->target = pdev; | ||
990 | for (i = 0; i < MAX_USER_CARDS; i++) { | ||
991 | if (priv->cards[i].pdev == pdev) | ||
992 | break; | ||
993 | if (priv->cards[i].pdev == NULL) { | ||
994 | priv->cards[i].pdev = pdev; | ||
995 | priv->cards[i].io_cnt = 0; | ||
996 | priv->cards[i].mem_cnt = 0; | ||
997 | break; | ||
998 | } | ||
999 | } | ||
1000 | if (i == MAX_USER_CARDS) { | ||
1001 | pr_err("vgaarb: maximum user cards number reached!\n"); | ||
1002 | pci_dev_put(pdev); | ||
1003 | /* XXX: which value to return? */ | ||
1004 | ret_val = -ENOMEM; | ||
1005 | goto done; | ||
1006 | } | ||
1007 | |||
1008 | ret_val = count; | ||
1009 | pci_dev_put(pdev); | ||
1010 | goto done; | ||
1011 | |||
1012 | |||
1013 | } else if (strncmp(curr_pos, "decodes ", 8) == 0) { | ||
1014 | curr_pos += 8; | ||
1015 | remaining -= 8; | ||
1016 | pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv); | ||
1017 | |||
1018 | if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { | ||
1019 | ret_val = -EPROTO; | ||
1020 | goto done; | ||
1021 | } | ||
1022 | pdev = priv->target; | ||
1023 | if (priv->target == NULL) { | ||
1024 | ret_val = -ENODEV; | ||
1025 | goto done; | ||
1026 | } | ||
1027 | |||
1028 | __vga_set_legacy_decoding(pdev, io_state, true); | ||
1029 | ret_val = count; | ||
1030 | goto done; | ||
1031 | } | ||
1032 | /* If we got here, the message written is not part of the protocol! */ | ||
1033 | kfree(kbuf); | ||
1034 | return -EPROTO; | ||
1035 | |||
1036 | done: | ||
1037 | kfree(kbuf); | ||
1038 | return ret_val; | ||
1039 | } | ||
1040 | |||
1041 | static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait) | ||
1042 | { | ||
1043 | struct vga_arb_private *priv = file->private_data; | ||
1044 | |||
1045 | pr_devel("%s\n", __func__); | ||
1046 | |||
1047 | if (priv == NULL) | ||
1048 | return -ENODEV; | ||
1049 | poll_wait(file, &vga_wait_queue, wait); | ||
1050 | return POLLIN; | ||
1051 | } | ||
1052 | |||
1053 | static int vga_arb_open(struct inode *inode, struct file *file) | ||
1054 | { | ||
1055 | struct vga_arb_private *priv; | ||
1056 | unsigned long flags; | ||
1057 | |||
1058 | pr_devel("%s\n", __func__); | ||
1059 | |||
1060 | priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL); | ||
1061 | if (priv == NULL) | ||
1062 | return -ENOMEM; | ||
1063 | memset(priv, 0, sizeof(*priv)); | ||
1064 | spin_lock_init(&priv->lock); | ||
1065 | file->private_data = priv; | ||
1066 | |||
1067 | spin_lock_irqsave(&vga_user_lock, flags); | ||
1068 | list_add(&priv->list, &vga_user_list); | ||
1069 | spin_unlock_irqrestore(&vga_user_lock, flags); | ||
1070 | |||
1071 | /* Set the client' lists of locks */ | ||
1072 | priv->target = vga_default_device(); /* Maybe this is still null! */ | ||
1073 | priv->cards[0].pdev = priv->target; | ||
1074 | priv->cards[0].io_cnt = 0; | ||
1075 | priv->cards[0].mem_cnt = 0; | ||
1076 | |||
1077 | |||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | static int vga_arb_release(struct inode *inode, struct file *file) | ||
1082 | { | ||
1083 | struct vga_arb_private *priv = file->private_data; | ||
1084 | struct vga_arb_user_card *uc; | ||
1085 | unsigned long flags; | ||
1086 | int i; | ||
1087 | |||
1088 | pr_devel("%s\n", __func__); | ||
1089 | |||
1090 | if (priv == NULL) | ||
1091 | return -ENODEV; | ||
1092 | |||
1093 | spin_lock_irqsave(&vga_user_lock, flags); | ||
1094 | list_del(&priv->list); | ||
1095 | for (i = 0; i < MAX_USER_CARDS; i++) { | ||
1096 | uc = &priv->cards[i]; | ||
1097 | if (uc->pdev == NULL) | ||
1098 | continue; | ||
1099 | pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n", | ||
1100 | uc->io_cnt, uc->mem_cnt); | ||
1101 | while (uc->io_cnt--) | ||
1102 | vga_put(uc->pdev, VGA_RSRC_LEGACY_IO); | ||
1103 | while (uc->mem_cnt--) | ||
1104 | vga_put(uc->pdev, VGA_RSRC_LEGACY_MEM); | ||
1105 | } | ||
1106 | spin_unlock_irqrestore(&vga_user_lock, flags); | ||
1107 | |||
1108 | kfree(priv); | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static void vga_arb_device_card_gone(struct pci_dev *pdev) | ||
1114 | { | ||
1115 | } | ||
1116 | |||
1117 | /* | ||
1118 | * callback any registered clients to let them know we have a | ||
1119 | * change in VGA cards | ||
1120 | */ | ||
1121 | static void vga_arbiter_notify_clients(void) | ||
1122 | { | ||
1123 | struct vga_device *vgadev; | ||
1124 | unsigned long flags; | ||
1125 | uint32_t new_decodes; | ||
1126 | bool new_state; | ||
1127 | |||
1128 | if (!vga_arbiter_used) | ||
1129 | return; | ||
1130 | |||
1131 | spin_lock_irqsave(&vga_lock, flags); | ||
1132 | list_for_each_entry(vgadev, &vga_list, list) { | ||
1133 | if (vga_count > 1) | ||
1134 | new_state = false; | ||
1135 | else | ||
1136 | new_state = true; | ||
1137 | if (vgadev->set_vga_decode) { | ||
1138 | new_decodes = vgadev->set_vga_decode(vgadev->cookie, new_state); | ||
1139 | vga_update_device_decodes(vgadev, new_decodes); | ||
1140 | } | ||
1141 | } | ||
1142 | spin_unlock_irqrestore(&vga_lock, flags); | ||
1143 | } | ||
1144 | |||
1145 | static int pci_notify(struct notifier_block *nb, unsigned long action, | ||
1146 | void *data) | ||
1147 | { | ||
1148 | struct device *dev = data; | ||
1149 | struct pci_dev *pdev = to_pci_dev(dev); | ||
1150 | bool notify = false; | ||
1151 | |||
1152 | pr_devel("%s\n", __func__); | ||
1153 | |||
1154 | /* For now we're only intereted in devices added and removed. I didn't | ||
1155 | * test this thing here, so someone needs to double check for the | ||
1156 | * cases of hotplugable vga cards. */ | ||
1157 | if (action == BUS_NOTIFY_ADD_DEVICE) | ||
1158 | notify = vga_arbiter_add_pci_device(pdev); | ||
1159 | else if (action == BUS_NOTIFY_DEL_DEVICE) | ||
1160 | notify = vga_arbiter_del_pci_device(pdev); | ||
1161 | |||
1162 | if (notify) | ||
1163 | vga_arbiter_notify_clients(); | ||
1164 | return 0; | ||
1165 | } | ||
1166 | |||
1167 | static struct notifier_block pci_notifier = { | ||
1168 | .notifier_call = pci_notify, | ||
1169 | }; | ||
1170 | |||
1171 | static const struct file_operations vga_arb_device_fops = { | ||
1172 | .read = vga_arb_read, | ||
1173 | .write = vga_arb_write, | ||
1174 | .poll = vga_arb_fpoll, | ||
1175 | .open = vga_arb_open, | ||
1176 | .release = vga_arb_release, | ||
1177 | }; | ||
1178 | |||
1179 | static struct miscdevice vga_arb_device = { | ||
1180 | MISC_DYNAMIC_MINOR, "vga_arbiter", &vga_arb_device_fops | ||
1181 | }; | ||
1182 | |||
1183 | static int __init vga_arb_device_init(void) | ||
1184 | { | ||
1185 | int rc; | ||
1186 | struct pci_dev *pdev; | ||
1187 | |||
1188 | rc = misc_register(&vga_arb_device); | ||
1189 | if (rc < 0) | ||
1190 | pr_err("vgaarb: error %d registering device\n", rc); | ||
1191 | |||
1192 | bus_register_notifier(&pci_bus_type, &pci_notifier); | ||
1193 | |||
1194 | /* We add all pci devices satisfying vga class in the arbiter by | ||
1195 | * default */ | ||
1196 | pdev = NULL; | ||
1197 | while ((pdev = | ||
1198 | pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | ||
1199 | PCI_ANY_ID, pdev)) != NULL) | ||
1200 | vga_arbiter_add_pci_device(pdev); | ||
1201 | |||
1202 | pr_info("vgaarb: loaded\n"); | ||
1203 | return rc; | ||
1204 | } | ||
1205 | subsys_initcall(vga_arb_device_init); | ||