1 // SPDX-License-Identifier: GPL-2.0-only 2 /****************************************************************************** 3 * platform-pci.c 4 * 5 * Xen platform PCI device driver 6 * 7 * Authors: ssmith@xensource.com and stefano.stabellini@eu.citrix.com 8 * 9 * Copyright (c) 2005, Intel Corporation. 10 * Copyright (c) 2007, XenSource Inc. 11 * Copyright (c) 2010, Citrix 12 */ 13 14 15 #include <linux/interrupt.h> 16 #include <linux/io.h> 17 #include <linux/init.h> 18 #include <linux/pci.h> 19 20 #include <xen/platform_pci.h> 21 #include <xen/grant_table.h> 22 #include <xen/xenbus.h> 23 #include <xen/events.h> 24 #include <xen/hvm.h> 25 #include <xen/xen-ops.h> 26 27 #define DRV_NAME "xen-platform-pci" 28 29 #define PCI_DEVICE_ID_XEN_PLATFORM_XS61 0x0002 30 31 static unsigned long platform_mmio; 32 static unsigned long platform_mmio_alloc; 33 static unsigned long platform_mmiolen; 34 static uint64_t callback_via; 35 36 static unsigned long alloc_xen_mmio(unsigned long len) 37 { 38 unsigned long addr; 39 40 addr = platform_mmio + platform_mmio_alloc; 41 platform_mmio_alloc += len; 42 BUG_ON(platform_mmio_alloc > platform_mmiolen); 43 44 return addr; 45 } 46 47 static uint64_t get_callback_via(struct pci_dev *pdev) 48 { 49 u8 pin; 50 int irq; 51 52 irq = pdev->irq; 53 if (irq < 16) 54 return irq; /* ISA IRQ */ 55 56 pin = pdev->pin; 57 58 /* We don't know the GSI. Specify the PCI INTx line instead. */ 59 return ((uint64_t)HVM_PARAM_CALLBACK_TYPE_PCI_INTX << 60 HVM_CALLBACK_VIA_TYPE_SHIFT) | 61 ((uint64_t)pci_domain_nr(pdev->bus) << 32) | 62 ((uint64_t)pdev->bus->number << 16) | 63 ((uint64_t)(pdev->devfn & 0xff) << 8) | 64 ((uint64_t)(pin - 1) & 3); 65 } 66 67 static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id) 68 { 69 return xen_evtchn_do_upcall(); 70 } 71 72 static int xen_allocate_irq(struct pci_dev *pdev) 73 { 74 return request_irq(pdev->irq, do_hvm_evtchn_intr, 75 IRQF_NOBALANCING | IRQF_SHARED, 76 "xen-platform-pci", pdev); 77 } 78 79 static int platform_pci_resume(struct device *dev) 80 { 81 int err; 82 83 if (xen_have_vector_callback) 84 return 0; 85 86 err = xen_set_callback_via(callback_via); 87 if (err) { 88 dev_err(dev, "platform_pci_resume failure!\n"); 89 return err; 90 } 91 return 0; 92 } 93 94 static int platform_pci_probe(struct pci_dev *pdev, 95 const struct pci_device_id *ent) 96 { 97 int i, ret; 98 long ioaddr; 99 long mmio_addr, mmio_len; 100 unsigned int max_nr_gframes; 101 unsigned long grant_frames; 102 103 if (!xen_domain()) 104 return -ENODEV; 105 106 i = pci_enable_device(pdev); 107 if (i) 108 return i; 109 110 ioaddr = pci_resource_start(pdev, 0); 111 112 mmio_addr = pci_resource_start(pdev, 1); 113 mmio_len = pci_resource_len(pdev, 1); 114 115 if (mmio_addr == 0 || ioaddr == 0) { 116 dev_err(&pdev->dev, "no resources found\n"); 117 ret = -ENOENT; 118 goto pci_out; 119 } 120 121 ret = pci_request_region(pdev, 1, DRV_NAME); 122 if (ret < 0) 123 goto pci_out; 124 125 ret = pci_request_region(pdev, 0, DRV_NAME); 126 if (ret < 0) 127 goto mem_out; 128 129 platform_mmio = mmio_addr; 130 platform_mmiolen = mmio_len; 131 if (!xen_have_vector_callback) { 132 ret = xen_allocate_irq(pdev); 133 if (ret) { 134 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); 135 goto out; 136 } 137 /* 138 * It doesn't strictly *have* to run on CPU0 but it sure 139 * as hell better process the event channel ports delivered 140 * to CPU0. 141 */ 142 irq_set_affinity(pdev->irq, cpumask_of(0)); 143 144 callback_via = get_callback_via(pdev); 145 ret = xen_set_callback_via(callback_via); 146 if (ret) { 147 dev_warn(&pdev->dev, "Unable to set the evtchn callback " 148 "err=%d\n", ret); 149 goto irq_out; 150 } 151 } 152 153 max_nr_gframes = gnttab_max_grant_frames(); 154 grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); 155 ret = gnttab_setup_auto_xlat_frames(grant_frames); 156 if (ret) 157 goto irq_out; 158 ret = gnttab_init(); 159 if (ret) 160 goto grant_out; 161 return 0; 162 grant_out: 163 gnttab_free_auto_xlat_frames(); 164 irq_out: 165 if (!xen_have_vector_callback) 166 free_irq(pdev->irq, pdev); 167 out: 168 pci_release_region(pdev, 0); 169 mem_out: 170 pci_release_region(pdev, 1); 171 pci_out: 172 pci_disable_device(pdev); 173 return ret; 174 } 175 176 static const struct pci_device_id platform_pci_tbl[] = { 177 {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM, 178 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 179 {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM_XS61, 180 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 181 {0,} 182 }; 183 184 static const struct dev_pm_ops platform_pm_ops = { 185 .resume_noirq = platform_pci_resume, 186 }; 187 188 static struct pci_driver platform_driver = { 189 .name = DRV_NAME, 190 .probe = platform_pci_probe, 191 .id_table = platform_pci_tbl, 192 .driver = { 193 .pm = &platform_pm_ops, 194 }, 195 }; 196 197 builtin_pci_driver(platform_driver); 198