ia64/xen-unstable

view unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @ 19848:5839491bbf20

[IA64] replace MAX_VCPUS with d->max_vcpus where necessary.

don't use MAX_VCPUS, and use vcpu::max_vcpus.
The changeset of 2f9e1348aa98 introduced max_vcpus to allow more vcpus
per guest. This patch is ia64 counter part.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 11:26:05 2009 +0900 (2009-06-29)
parents 8d993552673a
children
line source
1 /******************************************************************************
2 * platform-pci.c
3 *
4 * Xen platform PCI device driver
5 * Copyright (c) 2005, Intel Corporation.
6 * Copyright (c) 2007, XenSource Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place - Suite 330, Boston, MA 02111-1307 USA.
20 *
21 */
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/errno.h>
27 #include <linux/pci.h>
28 #include <linux/init.h>
29 #include <linux/version.h>
30 #include <linux/interrupt.h>
31 #include <linux/vmalloc.h>
32 #include <linux/mm.h>
33 #include <asm/system.h>
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/uaccess.h>
37 #include <asm/hypervisor.h>
38 #include <asm/pgtable.h>
39 #include <xen/interface/memory.h>
40 #include <xen/interface/hvm/params.h>
41 #include <xen/features.h>
42 #include <xen/evtchn.h>
43 #ifdef __ia64__
44 #include <asm/xen/xencomm.h>
45 #endif
47 #include "platform-pci.h"
49 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
50 #include <xen/platform-compat.h>
51 #endif
53 #define DRV_NAME "xen-platform-pci"
54 #define DRV_VERSION "0.10"
55 #define DRV_RELDATE "03/03/2005"
57 static int max_hypercall_stub_pages, nr_hypercall_stub_pages;
58 char *hypercall_stubs;
59 EXPORT_SYMBOL(hypercall_stubs);
61 MODULE_AUTHOR("ssmith@xensource.com");
62 MODULE_DESCRIPTION("Xen platform PCI device");
63 MODULE_LICENSE("GPL");
65 struct pci_dev *xen_platform_pdev;
67 static unsigned long shared_info_frame;
68 static uint64_t callback_via;
70 static int __devinit init_xen_info(void)
71 {
72 struct xen_add_to_physmap xatp;
73 extern void *shared_info_area;
75 #ifdef __ia64__
76 xencomm_initialize();
77 #endif
79 setup_xen_features();
81 shared_info_frame = alloc_xen_mmio(PAGE_SIZE) >> PAGE_SHIFT;
82 xatp.domid = DOMID_SELF;
83 xatp.idx = 0;
84 xatp.space = XENMAPSPACE_shared_info;
85 xatp.gpfn = shared_info_frame;
86 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
87 BUG();
89 shared_info_area =
90 ioremap(shared_info_frame << PAGE_SHIFT, PAGE_SIZE);
91 if (shared_info_area == NULL)
92 panic("can't map shared info\n");
94 return 0;
95 }
97 static unsigned long platform_mmio;
98 static unsigned long platform_mmio_alloc;
99 static unsigned long platform_mmiolen;
101 unsigned long alloc_xen_mmio(unsigned long len)
102 {
103 unsigned long addr;
105 addr = platform_mmio + platform_mmio_alloc;
106 platform_mmio_alloc += len;
107 BUG_ON(platform_mmio_alloc > platform_mmiolen);
109 return addr;
110 }
112 #ifndef __ia64__
114 static uint32_t xen_cpuid_base(void)
115 {
116 uint32_t base, eax, ebx, ecx, edx;
117 char signature[13];
119 for (base = 0x40000000; base < 0x40001000; base += 0x100) {
120 cpuid(base, &eax, &ebx, &ecx, &edx);
121 *(uint32_t*)(signature + 0) = ebx;
122 *(uint32_t*)(signature + 4) = ecx;
123 *(uint32_t*)(signature + 8) = edx;
124 signature[12] = 0;
126 if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
127 return base;
128 }
130 return 0;
131 }
133 static int init_hypercall_stubs(void)
134 {
135 uint32_t eax, ebx, ecx, edx, pages, msr, i, base;
137 base = xen_cpuid_base();
138 if (base == 0) {
139 printk(KERN_WARNING
140 "Detected Xen platform device but not Xen VMM?\n");
141 return -EINVAL;
142 }
144 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
146 printk(KERN_INFO "Xen version %d.%d.\n", eax >> 16, eax & 0xffff);
148 /*
149 * Find largest supported number of hypercall pages.
150 * We'll create as many as possible up to this number.
151 */
152 cpuid(base + 2, &pages, &msr, &ecx, &edx);
154 /*
155 * Use __vmalloc() because vmalloc_exec() is not an exported symbol.
156 * PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL.
157 * hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE);
158 */
159 while (pages > 0) {
160 hypercall_stubs = __vmalloc(
161 pages * PAGE_SIZE,
162 GFP_KERNEL | __GFP_HIGHMEM,
163 __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
164 if (hypercall_stubs != NULL)
165 break;
166 pages--; /* vmalloc failed: try one fewer pages */
167 }
169 if (hypercall_stubs == NULL)
170 return -ENOMEM;
172 for (i = 0; i < pages; i++) {
173 unsigned long pfn;
174 pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
175 wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
176 }
178 nr_hypercall_stub_pages = pages;
179 max_hypercall_stub_pages = pages;
181 printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
183 return 0;
184 }
186 static void resume_hypercall_stubs(void)
187 {
188 uint32_t base, ecx, edx, pages, msr, i;
190 base = xen_cpuid_base();
191 BUG_ON(base == 0);
193 cpuid(base + 2, &pages, &msr, &ecx, &edx);
195 if (pages > max_hypercall_stub_pages)
196 pages = max_hypercall_stub_pages;
198 for (i = 0; i < pages; i++) {
199 unsigned long pfn;
200 pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
201 wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
202 }
204 nr_hypercall_stub_pages = pages;
205 }
207 #else /* __ia64__ */
209 #define init_hypercall_stubs() (0)
210 #define resume_hypercall_stubs() ((void)0)
212 #endif
214 static uint64_t get_callback_via(struct pci_dev *pdev)
215 {
216 u8 pin;
217 int irq;
219 #ifdef __ia64__
220 for (irq = 0; irq < 16; irq++) {
221 if (isa_irq_to_vector(irq) == pdev->irq)
222 return irq; /* ISA IRQ */
223 }
224 #else /* !__ia64__ */
225 irq = pdev->irq;
226 if (irq < 16)
227 return irq; /* ISA IRQ */
228 #endif
230 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
231 pin = pdev->pin;
232 #else
233 pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
234 #endif
236 /* We don't know the GSI. Specify the PCI INTx line instead. */
237 return (((uint64_t)0x01 << 56) | /* PCI INTx identifier */
238 ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
239 ((uint64_t)pdev->bus->number << 16) |
240 ((uint64_t)(pdev->devfn & 0xff) << 8) |
241 ((uint64_t)(pin - 1) & 3));
242 }
244 static int set_callback_via(uint64_t via)
245 {
246 struct xen_hvm_param a;
248 a.domid = DOMID_SELF;
249 a.index = HVM_PARAM_CALLBACK_IRQ;
250 a.value = via;
251 return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
252 }
254 int xen_irq_init(struct pci_dev *pdev);
255 int xenbus_init(void);
256 int xen_reboot_init(void);
257 int xen_panic_handler_init(void);
258 int gnttab_init(void);
260 static int __devinit platform_pci_init(struct pci_dev *pdev,
261 const struct pci_device_id *ent)
262 {
263 int i, ret;
264 long ioaddr, iolen;
265 long mmio_addr, mmio_len;
267 if (xen_platform_pdev)
268 return -EBUSY;
269 xen_platform_pdev = pdev;
271 i = pci_enable_device(pdev);
272 if (i)
273 return i;
275 ioaddr = pci_resource_start(pdev, 0);
276 iolen = pci_resource_len(pdev, 0);
278 mmio_addr = pci_resource_start(pdev, 1);
279 mmio_len = pci_resource_len(pdev, 1);
281 callback_via = get_callback_via(pdev);
283 if (mmio_addr == 0 || ioaddr == 0 || callback_via == 0) {
284 printk(KERN_WARNING DRV_NAME ":no resources found\n");
285 return -ENOENT;
286 }
288 if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
289 printk(KERN_ERR ":MEM I/O resource 0x%lx @ 0x%lx busy\n",
290 mmio_addr, mmio_len);
291 return -EBUSY;
292 }
294 if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
295 printk(KERN_ERR DRV_NAME ":I/O resource 0x%lx @ 0x%lx busy\n",
296 iolen, ioaddr);
297 release_mem_region(mmio_addr, mmio_len);
298 return -EBUSY;
299 }
301 platform_mmio = mmio_addr;
302 platform_mmiolen = mmio_len;
304 ret = init_hypercall_stubs();
305 if (ret < 0)
306 goto out;
308 if ((ret = init_xen_info()))
309 goto out;
311 if ((ret = gnttab_init()))
312 goto out;
314 if ((ret = xen_irq_init(pdev)))
315 goto out;
317 if ((ret = set_callback_via(callback_via)))
318 goto out;
320 if ((ret = xenbus_init()))
321 goto out;
323 if ((ret = xen_reboot_init()))
324 goto out;
326 if ((ret = xen_panic_handler_init()))
327 goto out;
329 out:
330 if (ret) {
331 release_mem_region(mmio_addr, mmio_len);
332 release_region(ioaddr, iolen);
333 }
335 return ret;
336 }
338 #define XEN_PLATFORM_VENDOR_ID 0x5853
339 #define XEN_PLATFORM_DEVICE_ID 0x0001
340 static struct pci_device_id platform_pci_tbl[] __devinitdata = {
341 {XEN_PLATFORM_VENDOR_ID, XEN_PLATFORM_DEVICE_ID,
342 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
343 /* Continue to recognise the old ID for now */
344 {0xfffd, 0x0101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
345 {0,}
346 };
348 MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
350 static struct pci_driver platform_driver = {
351 name: DRV_NAME,
352 probe: platform_pci_init,
353 id_table: platform_pci_tbl,
354 };
356 static int pci_device_registered;
358 void platform_pci_resume(void)
359 {
360 struct xen_add_to_physmap xatp;
362 resume_hypercall_stubs();
364 xatp.domid = DOMID_SELF;
365 xatp.idx = 0;
366 xatp.space = XENMAPSPACE_shared_info;
367 xatp.gpfn = shared_info_frame;
368 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
369 BUG();
371 if (set_callback_via(callback_via))
372 printk("platform_pci_resume failure!\n");
373 }
375 static int __init platform_pci_module_init(void)
376 {
377 int rc;
379 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
380 rc = pci_module_init(&platform_driver);
381 #else
382 rc = pci_register_driver(&platform_driver);
383 #endif
384 if (rc) {
385 printk(KERN_INFO DRV_NAME
386 ": No platform pci device model found\n");
387 return rc;
388 }
390 pci_device_registered = 1;
391 return 0;
392 }
394 module_init(platform_pci_module_init);