root/drivers/xen/platform-pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. alloc_xen_mmio
  2. get_callback_via
  3. do_hvm_evtchn_intr
  4. xen_allocate_irq
  5. platform_pci_resume
  6. platform_pci_probe

   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 static unsigned long platform_mmio;
  30 static unsigned long platform_mmio_alloc;
  31 static unsigned long platform_mmiolen;
  32 static uint64_t callback_via;
  33 
  34 static unsigned long alloc_xen_mmio(unsigned long len)
  35 {
  36         unsigned long addr;
  37 
  38         addr = platform_mmio + platform_mmio_alloc;
  39         platform_mmio_alloc += len;
  40         BUG_ON(platform_mmio_alloc > platform_mmiolen);
  41 
  42         return addr;
  43 }
  44 
  45 static uint64_t get_callback_via(struct pci_dev *pdev)
  46 {
  47         u8 pin;
  48         int irq;
  49 
  50         irq = pdev->irq;
  51         if (irq < 16)
  52                 return irq; /* ISA IRQ */
  53 
  54         pin = pdev->pin;
  55 
  56         /* We don't know the GSI. Specify the PCI INTx line instead. */
  57         return ((uint64_t)0x01 << HVM_CALLBACK_VIA_TYPE_SHIFT) | /* PCI INTx identifier */
  58                 ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
  59                 ((uint64_t)pdev->bus->number << 16) |
  60                 ((uint64_t)(pdev->devfn & 0xff) << 8) |
  61                 ((uint64_t)(pin - 1) & 3);
  62 }
  63 
  64 static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
  65 {
  66         xen_hvm_evtchn_do_upcall();
  67         return IRQ_HANDLED;
  68 }
  69 
  70 static int xen_allocate_irq(struct pci_dev *pdev)
  71 {
  72         return request_irq(pdev->irq, do_hvm_evtchn_intr,
  73                         IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
  74                         "xen-platform-pci", pdev);
  75 }
  76 
  77 static int platform_pci_resume(struct pci_dev *pdev)
  78 {
  79         int err;
  80 
  81         if (xen_have_vector_callback)
  82                 return 0;
  83 
  84         err = xen_set_callback_via(callback_via);
  85         if (err) {
  86                 dev_err(&pdev->dev, "platform_pci_resume failure!\n");
  87                 return err;
  88         }
  89         return 0;
  90 }
  91 
  92 static int platform_pci_probe(struct pci_dev *pdev,
  93                               const struct pci_device_id *ent)
  94 {
  95         int i, ret;
  96         long ioaddr;
  97         long mmio_addr, mmio_len;
  98         unsigned int max_nr_gframes;
  99         unsigned long grant_frames;
 100 
 101         if (!xen_domain())
 102                 return -ENODEV;
 103 
 104         i = pci_enable_device(pdev);
 105         if (i)
 106                 return i;
 107 
 108         ioaddr = pci_resource_start(pdev, 0);
 109 
 110         mmio_addr = pci_resource_start(pdev, 1);
 111         mmio_len = pci_resource_len(pdev, 1);
 112 
 113         if (mmio_addr == 0 || ioaddr == 0) {
 114                 dev_err(&pdev->dev, "no resources found\n");
 115                 ret = -ENOENT;
 116                 goto pci_out;
 117         }
 118 
 119         ret = pci_request_region(pdev, 1, DRV_NAME);
 120         if (ret < 0)
 121                 goto pci_out;
 122 
 123         ret = pci_request_region(pdev, 0, DRV_NAME);
 124         if (ret < 0)
 125                 goto mem_out;
 126 
 127         platform_mmio = mmio_addr;
 128         platform_mmiolen = mmio_len;
 129         if (!xen_have_vector_callback) {
 130                 ret = xen_allocate_irq(pdev);
 131                 if (ret) {
 132                         dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
 133                         goto out;
 134                 }
 135                 callback_via = get_callback_via(pdev);
 136                 ret = xen_set_callback_via(callback_via);
 137                 if (ret) {
 138                         dev_warn(&pdev->dev, "Unable to set the evtchn callback "
 139                                          "err=%d\n", ret);
 140                         goto out;
 141                 }
 142         }
 143 
 144         max_nr_gframes = gnttab_max_grant_frames();
 145         grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
 146         ret = gnttab_setup_auto_xlat_frames(grant_frames);
 147         if (ret)
 148                 goto out;
 149         ret = gnttab_init();
 150         if (ret)
 151                 goto grant_out;
 152         xenbus_probe(NULL);
 153         return 0;
 154 grant_out:
 155         gnttab_free_auto_xlat_frames();
 156 out:
 157         pci_release_region(pdev, 0);
 158 mem_out:
 159         pci_release_region(pdev, 1);
 160 pci_out:
 161         pci_disable_device(pdev);
 162         return ret;
 163 }
 164 
 165 static const struct pci_device_id platform_pci_tbl[] = {
 166         {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
 167                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 168         {0,}
 169 };
 170 
 171 static struct pci_driver platform_driver = {
 172         .name =           DRV_NAME,
 173         .probe =          platform_pci_probe,
 174         .id_table =       platform_pci_tbl,
 175 #ifdef CONFIG_PM
 176         .resume_early =   platform_pci_resume,
 177 #endif
 178 };
 179 
 180 builtin_pci_driver(platform_driver);

/* [<][>][^][v][top][bottom][index][help] */