Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Pvpanic PCI Device Support
0004  *
0005  *  Copyright (C) 2021 Oracle.
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/pci.h>
0011 #include <linux/types.h>
0012 #include <linux/slab.h>
0013 
0014 #include <uapi/misc/pvpanic.h>
0015 
0016 #include "pvpanic.h"
0017 
0018 #define PCI_VENDOR_ID_REDHAT             0x1b36
0019 #define PCI_DEVICE_ID_REDHAT_PVPANIC     0x0011
0020 
0021 MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
0022 MODULE_DESCRIPTION("pvpanic device driver");
0023 MODULE_LICENSE("GPL");
0024 
0025 static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
0026 {
0027     struct pvpanic_instance *pi = dev_get_drvdata(dev);
0028 
0029     return sysfs_emit(buf, "%x\n", pi->capability);
0030 }
0031 static DEVICE_ATTR_RO(capability);
0032 
0033 static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
0034 {
0035     struct pvpanic_instance *pi = dev_get_drvdata(dev);
0036 
0037     return sysfs_emit(buf, "%x\n", pi->events);
0038 }
0039 
0040 static ssize_t events_store(struct device *dev, struct device_attribute *attr,
0041                 const char *buf, size_t count)
0042 {
0043     struct pvpanic_instance *pi = dev_get_drvdata(dev);
0044     unsigned int tmp;
0045     int err;
0046 
0047     err = kstrtouint(buf, 16, &tmp);
0048     if (err)
0049         return err;
0050 
0051     if ((tmp & pi->capability) != tmp)
0052         return -EINVAL;
0053 
0054     pi->events = tmp;
0055 
0056     return count;
0057 }
0058 static DEVICE_ATTR_RW(events);
0059 
0060 static struct attribute *pvpanic_pci_dev_attrs[] = {
0061     &dev_attr_capability.attr,
0062     &dev_attr_events.attr,
0063     NULL
0064 };
0065 ATTRIBUTE_GROUPS(pvpanic_pci_dev);
0066 
0067 static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0068 {
0069     struct pvpanic_instance *pi;
0070     void __iomem *base;
0071     int ret;
0072 
0073     ret = pcim_enable_device(pdev);
0074     if (ret < 0)
0075         return ret;
0076 
0077     base = pcim_iomap(pdev, 0, 0);
0078     if (!base)
0079         return -ENOMEM;
0080 
0081     pi = devm_kmalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
0082     if (!pi)
0083         return -ENOMEM;
0084 
0085     pi->base = base;
0086     pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
0087 
0088     /* initlize capability by RDPT */
0089     pi->capability &= ioread8(base);
0090     pi->events = pi->capability;
0091 
0092     return devm_pvpanic_probe(&pdev->dev, pi);
0093 }
0094 
0095 static const struct pci_device_id pvpanic_pci_id_tbl[]  = {
0096     { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PVPANIC)},
0097     {}
0098 };
0099 MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl);
0100 
0101 static struct pci_driver pvpanic_pci_driver = {
0102     .name =         "pvpanic-pci",
0103     .id_table =     pvpanic_pci_id_tbl,
0104     .probe =        pvpanic_pci_probe,
0105     .driver = {
0106         .dev_groups = pvpanic_pci_dev_groups,
0107     },
0108 };
0109 module_pci_driver(pvpanic_pci_driver);