ia64/xen-unstable

view xen/drivers/passthrough/pci.c @ 17997:a7ec5cc4fd08

Change PCI-dump debug key: Fixes boot with debug=y and perfc=y
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 08 17:03:53 2008 +0100 (2008-07-08)
parents 183ca809e1d7
children c1577f094ae4
line source
1 /*
2 * Copyright (C) 2008, Netronome Systems, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
16 */
18 #include <xen/sched.h>
19 #include <xen/pci.h>
20 #include <xen/list.h>
21 #include <xen/prefetch.h>
22 #include <xen/iommu.h>
23 #include <xen/keyhandler.h>
26 LIST_HEAD(alldevs_list);
27 rwlock_t pcidevs_lock = RW_LOCK_UNLOCKED;
29 struct pci_dev *alloc_pdev(u8 bus, u8 devfn)
30 {
31 struct pci_dev *pdev;
33 list_for_each_entry ( pdev, &alldevs_list, alldevs_list )
34 if ( pdev->bus == bus && pdev->devfn == devfn )
35 return pdev;
37 pdev = xmalloc(struct pci_dev);
38 if ( !pdev )
39 return NULL;
41 *((u8*) &pdev->bus) = bus;
42 *((u8*) &pdev->devfn) = devfn;
43 pdev->domain = NULL;
44 spin_lock_init(&pdev->lock);
45 INIT_LIST_HEAD(&pdev->msi_list);
46 list_add(&pdev->alldevs_list, &alldevs_list);
48 return pdev;
49 }
51 void free_pdev(struct pci_dev *pdev)
52 {
53 list_del(&pdev->alldevs_list);
54 xfree(pdev);
55 }
57 struct pci_dev *pci_lock_pdev(int bus, int devfn)
58 {
59 struct pci_dev *pdev;
61 read_lock(&pcidevs_lock);
62 list_for_each_entry ( pdev, &alldevs_list, alldevs_list )
63 if ( (pdev->bus == bus || bus == -1) &&
64 (pdev->devfn == devfn || devfn == -1) )
65 {
66 spin_lock(&pdev->lock);
67 read_unlock(&pcidevs_lock);
68 return pdev;
69 }
70 read_unlock(&pcidevs_lock);
72 return NULL;
73 }
75 struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn)
76 {
77 struct pci_dev *pdev;
79 read_lock(&pcidevs_lock);
80 list_for_each_entry ( pdev, &d->arch.pdev_list, domain_list )
81 {
82 spin_lock(&pdev->lock);
83 if ( (pdev->bus == bus || bus == -1) &&
84 (pdev->devfn == devfn || devfn == -1) &&
85 (pdev->domain == d) )
86 {
87 read_unlock(&pcidevs_lock);
88 return pdev;
89 }
90 spin_unlock(&pdev->lock);
91 }
92 read_unlock(&pcidevs_lock);
94 return NULL;
95 }
97 int pci_add_device(u8 bus, u8 devfn)
98 {
99 struct pci_dev *pdev;
100 int ret = -ENOMEM;
102 write_lock(&pcidevs_lock);
103 pdev = alloc_pdev(bus, devfn);
104 if ( !pdev )
105 goto out;
107 ret = 0;
108 spin_lock(&pdev->lock);
109 if ( !pdev->domain )
110 {
111 pdev->domain = dom0;
112 list_add(&pdev->domain_list, &dom0->arch.pdev_list);
113 ret = iommu_add_device(pdev);
114 }
115 spin_unlock(&pdev->lock);
116 printk(XENLOG_DEBUG "PCI add device %02x:%02x.%x\n", bus,
117 PCI_SLOT(devfn), PCI_FUNC(devfn));
119 out:
120 write_unlock(&pcidevs_lock);
121 return ret;
122 }
124 int pci_remove_device(u8 bus, u8 devfn)
125 {
126 struct pci_dev *pdev;
127 int ret = -ENODEV;;
129 write_lock(&pcidevs_lock);
130 list_for_each_entry ( pdev, &alldevs_list, alldevs_list )
131 if ( pdev->bus == bus && pdev->devfn == devfn )
132 {
133 spin_lock(&pdev->lock);
134 ret = iommu_remove_device(pdev);
135 if ( pdev->domain )
136 list_del(&pdev->domain_list);
137 pci_cleanup_msi(pdev);
138 free_pdev(pdev);
139 printk(XENLOG_DEBUG "PCI remove device %02x:%02x.%x\n", bus,
140 PCI_SLOT(devfn), PCI_FUNC(devfn));
141 break;
142 }
144 write_unlock(&pcidevs_lock);
145 return ret;
146 }
148 static void dump_pci_devices(unsigned char ch)
149 {
150 struct pci_dev *pdev;
151 struct msi_desc *msi;
153 printk("==== PCI devices ====\n");
154 read_lock(&pcidevs_lock);
156 list_for_each_entry ( pdev, &alldevs_list, alldevs_list )
157 {
158 spin_lock(&pdev->lock);
159 printk("%02x:%02x.%x - dom %-3d - MSIs < ",
160 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
161 pdev->domain ? pdev->domain->domain_id : -1);
162 list_for_each_entry ( msi, &pdev->msi_list, list )
163 printk("%d ", msi->vector);
164 printk(">\n");
165 spin_unlock(&pdev->lock);
166 }
168 read_unlock(&pcidevs_lock);
169 }
171 static int __init setup_dump_pcidevs(void)
172 {
173 register_keyhandler('Q', dump_pci_devices, "dump PCI devices");
174 return 0;
175 }
176 __initcall(setup_dump_pcidevs);