ia64/xen-unstable

view unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @ 11960:fd5140c2854f

Fix Memory assumptions in the create tests.

Use the architecture specified idea of minimum memory.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Oct 24 14:52:20 2006 +0100 (2006-10-24)
parents f872300b672f
children 7c2a5f96a192 e715360e82f8
line source
1 /******************************************************************************
2 * evtchn-pci.c
3 * xen event channel fake PCI device driver
4 * Copyright (C) 2005, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 */
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/errno.h>
25 #include <linux/pci.h>
26 #include <linux/init.h>
27 #include <linux/version.h>
28 #include <linux/interrupt.h>
29 #include <linux/vmalloc.h>
30 #include <linux/mm.h>
31 #include <asm/system.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/uaccess.h>
35 #include <asm/hypervisor.h>
36 #include <xen/interface/memory.h>
37 #include <xen/features.h>
39 #include "platform-pci.h"
41 #define DRV_NAME "xen-platform-pci"
42 #define DRV_VERSION "0.10"
43 #define DRV_RELDATE "03/03/2005"
45 char *hypercall_stubs;
46 EXPORT_SYMBOL(hypercall_stubs);
48 // Used to be xiaofeng.ling@intel.com
49 MODULE_AUTHOR("ssmith@xensource.com");
50 MODULE_DESCRIPTION("Xen platform PCI device");
51 MODULE_LICENSE("GPL");
53 unsigned long *phys_to_machine_mapping;
54 EXPORT_SYMBOL(phys_to_machine_mapping);
56 static int __init init_xen_info(void)
57 {
58 unsigned long shared_info_frame;
59 struct xen_add_to_physmap xatp;
60 extern void *shared_info_area;
62 setup_xen_features();
64 shared_info_frame = alloc_xen_mmio(PAGE_SIZE) >> PAGE_SHIFT;
65 xatp.domid = DOMID_SELF;
66 xatp.idx = 0;
67 xatp.space = XENMAPSPACE_shared_info;
68 xatp.gpfn = shared_info_frame;
69 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
70 BUG();
72 shared_info_area =
73 ioremap(shared_info_frame << PAGE_SHIFT, PAGE_SIZE);
74 if (shared_info_area == NULL)
75 panic("can't map shared info\n");
77 phys_to_machine_mapping = NULL;
79 gnttab_init();
81 return 0;
82 }
84 static void __devexit platform_pci_remove(struct pci_dev *pdev)
85 {
86 long ioaddr, iolen;
87 long mmio_addr, mmio_len;
89 ioaddr = pci_resource_start(pdev, 0);
90 iolen = pci_resource_len(pdev, 0);
91 mmio_addr = pci_resource_start(pdev, 1);
92 mmio_len = pci_resource_len(pdev, 1);
94 release_region(ioaddr, iolen);
95 release_mem_region(mmio_addr, mmio_len);
97 pci_set_drvdata(pdev, NULL);
98 free_irq(pdev->irq, pdev);
99 }
101 static unsigned long platform_mmio;
102 static unsigned long platform_mmio_alloc;
103 static unsigned long platform_mmiolen;
105 unsigned long alloc_xen_mmio(unsigned long len)
106 {
107 unsigned long addr;
109 addr = 0;
110 if (platform_mmio_alloc + len <= platform_mmiolen)
111 {
112 addr = platform_mmio + platform_mmio_alloc;
113 platform_mmio_alloc += len;
114 } else {
115 panic("ran out of xen mmio space");
116 }
117 return addr;
118 }
120 #ifndef __ia64__
121 /* Lifted from hvmloader.c */
122 static int get_hypercall_stubs(void)
123 {
124 uint32_t eax, ebx, ecx, edx, pages, msr, i;
125 char signature[13];
127 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
128 *(uint32_t*)(signature + 0) = ebx;
129 *(uint32_t*)(signature + 4) = ecx;
130 *(uint32_t*)(signature + 8) = edx;
131 signature[12] = 0;
133 if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) {
134 printk(KERN_WARNING
135 "Detected Xen platform device but not Xen VMM?"
136 " (sig %s, eax %x)\n",
137 signature, eax);
138 return -EINVAL;
139 }
141 cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
143 printk(KERN_INFO "Xen version %d.%d.\n", eax >> 16, eax & 0xffff);
145 cpuid(0x40000002, &pages, &msr, &ecx, &edx);
147 printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
149 /* Use __vmalloc() because vmalloc_exec() is not an exported symbol. */
150 /* PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL. */
151 /* hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE); */
152 hypercall_stubs = __vmalloc(pages * PAGE_SIZE,
153 GFP_KERNEL | __GFP_HIGHMEM,
154 __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
155 if (hypercall_stubs == NULL)
156 return -ENOMEM;
158 for (i = 0; i < pages; i++) {
159 unsigned long pfn;
160 pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
161 wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
162 }
164 return 0;
165 }
166 #else /* __ia64__ */
167 #define get_hypercall_stubs() (0)
168 #endif
170 static int __devinit platform_pci_init(struct pci_dev *pdev,
171 const struct pci_device_id *ent)
172 {
173 int i, ret;
174 long ioaddr, iolen;
175 long mmio_addr, mmio_len;
177 i = pci_enable_device(pdev);
178 if (i)
179 return i;
181 ioaddr = pci_resource_start(pdev, 0);
182 iolen = pci_resource_len(pdev, 0);
184 mmio_addr = pci_resource_start(pdev, 1);
185 mmio_len = pci_resource_len(pdev, 1);
187 if (mmio_addr == 0 || ioaddr == 0) {
188 printk(KERN_WARNING DRV_NAME ":no resources found\n");
189 return -ENOENT;
190 }
192 if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL)
193 {
194 printk(KERN_ERR ":MEM I/O resource 0x%lx @ 0x%lx busy\n",
195 mmio_addr, mmio_len);
196 return -EBUSY;
197 }
199 if (request_region(ioaddr, iolen, DRV_NAME) == NULL)
200 {
201 printk(KERN_ERR DRV_NAME ":I/O resource 0x%lx @ 0x%lx busy\n",
202 iolen, ioaddr);
203 release_mem_region(mmio_addr, mmio_len);
204 return -EBUSY;
205 }
207 platform_mmio = mmio_addr;
208 platform_mmiolen = mmio_len;
210 ret = get_hypercall_stubs();
211 if (ret < 0)
212 goto out;
214 if ((ret = init_xen_info()))
215 goto out;
217 if ((ret = request_irq(pdev->irq, evtchn_interrupt, SA_SHIRQ,
218 "xen-platform-pci", pdev))) {
219 goto out;
220 }
222 if ((ret = set_callback_irq(pdev->irq)))
223 goto out;
225 out:
226 if (ret) {
227 release_mem_region(mmio_addr, mmio_len);
228 release_region(ioaddr, iolen);
229 }
231 return ret;
232 }
234 #define XEN_PLATFORM_VENDOR_ID 0x5853
235 #define XEN_PLATFORM_DEVICE_ID 0x0001
236 static struct pci_device_id platform_pci_tbl[] __devinitdata = {
237 {XEN_PLATFORM_VENDOR_ID, XEN_PLATFORM_DEVICE_ID,
238 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
239 /* Continue to recognise the old ID for now */
240 {0xfffd, 0x0101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
241 {0,}
242 };
244 MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
246 static struct pci_driver platform_driver = {
247 name: DRV_NAME,
248 probe: platform_pci_init,
249 remove: __devexit_p(platform_pci_remove),
250 id_table: platform_pci_tbl,
251 };
253 static int pci_device_registered;
255 static int __init platform_pci_module_init(void)
256 {
257 int rc;
259 rc = pci_module_init(&platform_driver);
260 if (rc)
261 printk(KERN_INFO DRV_NAME ":No platform pci device model found\n");
262 else
263 pci_device_registered = 1;
265 return rc;
266 }
268 static void __exit platform_pci_module_cleanup(void)
269 {
270 printk(KERN_INFO DRV_NAME ":Do platform module cleanup\n");
271 /* disable hypervisor for callback irq */
272 set_callback_irq(0);
273 if (pci_device_registered)
274 pci_unregister_driver(&platform_driver);
275 }
277 module_init(platform_pci_module_init);
278 module_exit(platform_pci_module_cleanup);