2 * Copyright (c) 2009, Intel Corporation.
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.
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
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.
17 * Author: Weidong Han <weidong.han@intel.com>
20 #include <linux/pci.h>
22 #include <xen/interface/physdev.h>
23 #include <xen/interface/xen.h>
25 #include <asm/xen/hypervisor.h>
26 #include <asm/xen/hypercall.h>
27 #include "../pci/pci.h"
29 static int xen_add_device(struct device
*dev
)
32 struct pci_dev
*pci_dev
= to_pci_dev(dev
);
35 if (pci_dev
->is_virtfn
) {
36 struct physdev_manage_pci_ext manage_pci_ext
= {
37 .bus
= pci_dev
->bus
->number
,
38 .devfn
= pci_dev
->devfn
,
40 .physfn
.bus
= pci_dev
->physfn
->bus
->number
,
41 .physfn
.devfn
= pci_dev
->physfn
->devfn
,
44 r
= HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext
,
48 if (pci_ari_enabled(pci_dev
->bus
) && PCI_SLOT(pci_dev
->devfn
)) {
49 struct physdev_manage_pci_ext manage_pci_ext
= {
50 .bus
= pci_dev
->bus
->number
,
51 .devfn
= pci_dev
->devfn
,
55 r
= HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext
,
58 struct physdev_manage_pci manage_pci
= {
59 .bus
= pci_dev
->bus
->number
,
60 .devfn
= pci_dev
->devfn
,
63 r
= HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add
,
70 static int xen_remove_device(struct device
*dev
)
73 struct pci_dev
*pci_dev
= to_pci_dev(dev
);
74 struct physdev_manage_pci manage_pci
;
76 manage_pci
.bus
= pci_dev
->bus
->number
;
77 manage_pci
.devfn
= pci_dev
->devfn
;
79 r
= HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove
,
85 static int xen_pci_notifier(struct notifier_block
*nb
,
86 unsigned long action
, void *data
)
88 struct device
*dev
= data
;
92 case BUS_NOTIFY_ADD_DEVICE
:
93 r
= xen_add_device(dev
);
95 case BUS_NOTIFY_DEL_DEVICE
:
96 r
= xen_remove_device(dev
);
105 struct notifier_block device_nb
= {
106 .notifier_call
= xen_pci_notifier
,
109 static int __init
register_xen_pci_notifier(void)
111 if (!xen_initial_domain())
114 return bus_register_notifier(&pci_bus_type
, &device_nb
);
117 arch_initcall(register_xen_pci_notifier
);