root/drivers/misc/pvpanic.c

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

DEFINITIONS

This source file includes following definitions.
  1. pvpanic_send_event
  2. pvpanic_panic_notify
  3. pvpanic_walk_resources
  4. pvpanic_add
  5. pvpanic_remove
  6. pvpanic_register_acpi_driver
  7. pvpanic_unregister_acpi_driver
  8. pvpanic_register_acpi_driver
  9. pvpanic_unregister_acpi_driver
  10. pvpanic_mmio_probe
  11. pvpanic_mmio_remove
  12. pvpanic_mmio_init
  13. pvpanic_mmio_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  *  Pvpanic Device Support
   4  *
   5  *  Copyright (C) 2013 Fujitsu.
   6  *  Copyright (C) 2018 ZTE.
   7  */
   8 
   9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10 
  11 #include <linux/acpi.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 #include <linux/of_address.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/types.h>
  18 
  19 static void __iomem *base;
  20 
  21 #define PVPANIC_PANICKED        (1 << 0)
  22 
  23 MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
  24 MODULE_DESCRIPTION("pvpanic device driver");
  25 MODULE_LICENSE("GPL");
  26 
  27 static void
  28 pvpanic_send_event(unsigned int event)
  29 {
  30         iowrite8(event, base);
  31 }
  32 
  33 static int
  34 pvpanic_panic_notify(struct notifier_block *nb, unsigned long code,
  35                      void *unused)
  36 {
  37         pvpanic_send_event(PVPANIC_PANICKED);
  38         return NOTIFY_DONE;
  39 }
  40 
  41 static struct notifier_block pvpanic_panic_nb = {
  42         .notifier_call = pvpanic_panic_notify,
  43         .priority = 1, /* let this called before broken drm_fb_helper */
  44 };
  45 
  46 #ifdef CONFIG_ACPI
  47 static int pvpanic_add(struct acpi_device *device);
  48 static int pvpanic_remove(struct acpi_device *device);
  49 
  50 static const struct acpi_device_id pvpanic_device_ids[] = {
  51         { "QEMU0001", 0 },
  52         { "", 0 }
  53 };
  54 MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids);
  55 
  56 static struct acpi_driver pvpanic_driver = {
  57         .name =         "pvpanic",
  58         .class =        "QEMU",
  59         .ids =          pvpanic_device_ids,
  60         .ops =          {
  61                                 .add =          pvpanic_add,
  62                                 .remove =       pvpanic_remove,
  63                         },
  64         .owner =        THIS_MODULE,
  65 };
  66 
  67 static acpi_status
  68 pvpanic_walk_resources(struct acpi_resource *res, void *context)
  69 {
  70         struct resource r;
  71 
  72         if (acpi_dev_resource_io(res, &r)) {
  73 #ifdef CONFIG_HAS_IOPORT_MAP
  74                 base = ioport_map(r.start, resource_size(&r));
  75                 return AE_OK;
  76 #else
  77                 return AE_ERROR;
  78 #endif
  79         } else if (acpi_dev_resource_memory(res, &r)) {
  80                 base = ioremap(r.start, resource_size(&r));
  81                 return AE_OK;
  82         }
  83 
  84         return AE_ERROR;
  85 }
  86 
  87 static int pvpanic_add(struct acpi_device *device)
  88 {
  89         int ret;
  90 
  91         ret = acpi_bus_get_status(device);
  92         if (ret < 0)
  93                 return ret;
  94 
  95         if (!device->status.enabled || !device->status.functional)
  96                 return -ENODEV;
  97 
  98         acpi_walk_resources(device->handle, METHOD_NAME__CRS,
  99                             pvpanic_walk_resources, NULL);
 100 
 101         if (!base)
 102                 return -ENODEV;
 103 
 104         atomic_notifier_chain_register(&panic_notifier_list,
 105                                        &pvpanic_panic_nb);
 106 
 107         return 0;
 108 }
 109 
 110 static int pvpanic_remove(struct acpi_device *device)
 111 {
 112 
 113         atomic_notifier_chain_unregister(&panic_notifier_list,
 114                                          &pvpanic_panic_nb);
 115         iounmap(base);
 116 
 117         return 0;
 118 }
 119 
 120 static int pvpanic_register_acpi_driver(void)
 121 {
 122         return acpi_bus_register_driver(&pvpanic_driver);
 123 }
 124 
 125 static void pvpanic_unregister_acpi_driver(void)
 126 {
 127         acpi_bus_unregister_driver(&pvpanic_driver);
 128 }
 129 #else
 130 static int pvpanic_register_acpi_driver(void)
 131 {
 132         return -ENODEV;
 133 }
 134 
 135 static void pvpanic_unregister_acpi_driver(void) {}
 136 #endif
 137 
 138 static int pvpanic_mmio_probe(struct platform_device *pdev)
 139 {
 140         struct resource *mem;
 141 
 142         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 143         if (!mem)
 144                 return -EINVAL;
 145 
 146         base = devm_ioremap_resource(&pdev->dev, mem);
 147         if (IS_ERR(base))
 148                 return PTR_ERR(base);
 149 
 150         atomic_notifier_chain_register(&panic_notifier_list,
 151                                        &pvpanic_panic_nb);
 152 
 153         return 0;
 154 }
 155 
 156 static int pvpanic_mmio_remove(struct platform_device *pdev)
 157 {
 158 
 159         atomic_notifier_chain_unregister(&panic_notifier_list,
 160                                          &pvpanic_panic_nb);
 161 
 162         return 0;
 163 }
 164 
 165 static const struct of_device_id pvpanic_mmio_match[] = {
 166         { .compatible = "qemu,pvpanic-mmio", },
 167         {}
 168 };
 169 
 170 static struct platform_driver pvpanic_mmio_driver = {
 171         .driver = {
 172                 .name = "pvpanic-mmio",
 173                 .of_match_table = pvpanic_mmio_match,
 174         },
 175         .probe = pvpanic_mmio_probe,
 176         .remove = pvpanic_mmio_remove,
 177 };
 178 
 179 static int __init pvpanic_mmio_init(void)
 180 {
 181         if (acpi_disabled)
 182                 return platform_driver_register(&pvpanic_mmio_driver);
 183         else
 184                 return pvpanic_register_acpi_driver();
 185 }
 186 
 187 static void __exit pvpanic_mmio_exit(void)
 188 {
 189         if (acpi_disabled)
 190                 platform_driver_unregister(&pvpanic_mmio_driver);
 191         else
 192                 pvpanic_unregister_acpi_driver();
 193 }
 194 
 195 module_init(pvpanic_mmio_init);
 196 module_exit(pvpanic_mmio_exit);

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