2021-03-24 16:49:16 +02:00
// SPDX-License-Identifier: GPL-2.0+
/*
* Pvpanic PCI Device Support
*
* Copyright ( C ) 2021 Oracle .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/types.h>
# include <linux/slab.h>
# include <uapi/misc/pvpanic.h>
# include "pvpanic.h"
# define PCI_VENDOR_ID_REDHAT 0x1b36
# define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
MODULE_AUTHOR ( " Mihai Carabas <mihai.carabas@oracle.com> " ) ;
2021-08-29 15:43:54 +03:00
MODULE_DESCRIPTION ( " pvpanic device driver " ) ;
2021-03-24 16:49:16 +02:00
MODULE_LICENSE ( " GPL " ) ;
2021-08-29 15:43:54 +03:00
static ssize_t capability_show ( struct device * dev , struct device_attribute * attr , char * buf )
2021-03-24 16:49:16 +02:00
{
struct pvpanic_instance * pi = dev_get_drvdata ( dev ) ;
return sysfs_emit ( buf , " %x \n " , pi - > capability ) ;
}
static DEVICE_ATTR_RO ( capability ) ;
2021-08-29 15:43:54 +03:00
static ssize_t events_show ( struct device * dev , struct device_attribute * attr , char * buf )
2021-03-24 16:49:16 +02:00
{
struct pvpanic_instance * pi = dev_get_drvdata ( dev ) ;
return sysfs_emit ( buf , " %x \n " , pi - > events ) ;
}
2021-08-29 15:43:54 +03:00
static ssize_t events_store ( struct device * dev , struct device_attribute * attr ,
2021-03-24 16:49:16 +02:00
const char * buf , size_t count )
{
struct pvpanic_instance * pi = dev_get_drvdata ( dev ) ;
unsigned int tmp ;
int err ;
err = kstrtouint ( buf , 16 , & tmp ) ;
if ( err )
return err ;
if ( ( tmp & pi - > capability ) ! = tmp )
return - EINVAL ;
pi - > events = tmp ;
return count ;
}
static DEVICE_ATTR_RW ( events ) ;
static struct attribute * pvpanic_pci_dev_attrs [ ] = {
& dev_attr_capability . attr ,
& dev_attr_events . attr ,
NULL
} ;
ATTRIBUTE_GROUPS ( pvpanic_pci_dev ) ;
2021-08-29 15:43:54 +03:00
static int pvpanic_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
2021-03-24 16:49:16 +02:00
{
struct pvpanic_instance * pi ;
void __iomem * base ;
int ret ;
2021-05-22 08:54:33 +02:00
ret = pcim_enable_device ( pdev ) ;
2021-03-24 16:49:16 +02:00
if ( ret < 0 )
return ret ;
2021-05-22 08:54:33 +02:00
base = pcim_iomap ( pdev , 0 , 0 ) ;
2021-03-30 09:36:59 +08:00
if ( ! base )
return - ENOMEM ;
2021-03-24 16:49:16 +02:00
2021-05-22 08:54:52 +02:00
pi = devm_kmalloc ( & pdev - > dev , sizeof ( * pi ) , GFP_KERNEL ) ;
2021-03-24 16:49:16 +02:00
if ( ! pi )
return - ENOMEM ;
pi - > base = base ;
pi - > capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED ;
/* initlize capability by RDPT */
pi - > capability & = ioread8 ( base ) ;
pi - > events = pi - > capability ;
2021-05-22 08:55:20 +02:00
return devm_pvpanic_probe ( & pdev - > dev , pi ) ;
2021-03-24 16:49:16 +02:00
}
2021-08-29 15:43:52 +03:00
static const struct pci_device_id pvpanic_pci_id_tbl [ ] = {
{ PCI_DEVICE ( PCI_VENDOR_ID_REDHAT , PCI_DEVICE_ID_REDHAT_PVPANIC ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( pci , pvpanic_pci_id_tbl ) ;
2021-03-24 16:49:16 +02:00
static struct pci_driver pvpanic_pci_driver = {
. name = " pvpanic-pci " ,
. id_table = pvpanic_pci_id_tbl ,
. probe = pvpanic_pci_probe ,
. driver = {
. dev_groups = pvpanic_pci_dev_groups ,
} ,
} ;
module_pci_driver ( pvpanic_pci_driver ) ;